commit 0bac88e3bb33c388147e3446c4b6a186e3fef9dc
parent f5e296b7aff44a16e70dd68588e4204b169ca2c6
Author: Jared Tobin <jared@jtobin.ca>
Date: Sun, 28 May 2017 23:11:27 +1200
WIP.
Diffstat:
3 files changed, 359 insertions(+), 0 deletions(-)
diff --git a/lib/aes_cbc/Cargo.lock b/lib/aes_cbc/Cargo.lock
@@ -0,0 +1,197 @@
+[root]
+name = "aes_cbc"
+version = "0.1.0"
+dependencies = [
+ "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "ansi_term"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "atty"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "base64"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bitflags"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "byteorder"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "clap"
+version = "2.24.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "foreign-types"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "gcc"
+version = "0.3.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "gdi32-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lazy_static"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "openssl"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.49 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "strsim"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "term_size"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "user32-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "vec_map"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[metadata]
+"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
+"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
+"checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557"
+"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
+"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
+"checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f"
+"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
+"checksum gcc 0.3.49 (registry+https://github.com/rust-lang/crates.io-index)" = "9be730064c122681712957ba1a9abaf082150be8aaf94526a805d900015b65b9"
+"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
+"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
+"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e"
+"checksum openssl 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bb5d1663b73d10c6a3eda53e2e9d0346f822394e7b858d7257718f65f61dfbe2"
+"checksum openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3a5886d87d3e2a0d890bf62dc8944f5e3769a405f7e1e9ef6e517e47fd7a0897"
+"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
+"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
+"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
+"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946"
+"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
+"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
+"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
+"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
diff --git a/lib/aes_cbc/Cargo.toml b/lib/aes_cbc/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "aes_cbc"
+version = "0.1.0"
+authors = ["Jared Tobin <jared@jtobin.ca>"]
+
+[dependencies]
+
+base64 = "~0.5.0"
+clap = "2.24.2"
+openssl = "0.9.11"
diff --git a/lib/aes_cbc/src/main.rs b/lib/aes_cbc/src/main.rs
@@ -0,0 +1,152 @@
+
+// hat tip to ttaubert/rust-cryptopals for lots of help here
+
+extern crate base64;
+extern crate clap;
+extern crate openssl;
+
+use openssl::symm::{Cipher, Crypter, Mode};
+use std::io::{self, Read};
+use clap::{App, Arg};
+
+fn fixed_xor(target: Vec<u8>, partner: Vec<u8>) -> Vec<u8> {
+ assert_eq!(target.len(), partner.len());
+
+ target
+ .iter()
+ .zip(partner)
+ .map(|(&l, r)| l ^ r)
+ .collect()
+}
+
+fn new_crypter_unpadded(
+ cipher: Cipher,
+ mode: Mode,
+ key: &[u8],
+ iv: Option<&[u8]>
+ ) -> Crypter {
+
+ let mut crypter = match Crypter::new(cipher, mode, key, iv) {
+ Ok(val) => val,
+ Err(err) => panic!("{}", err)
+ };
+
+ crypter.pad(false);
+
+ crypter
+}
+
+fn ecb_128_crypt(mode: Mode, key: &[u8], text: &[u8]) -> Vec<u8> {
+ let cipher = Cipher::aes_128_ecb();
+ let iv = None;
+
+ let mut crypter = new_crypter_unpadded(cipher, mode, key, iv);
+ let mut result = vec![0; text.len() + cipher.key_len()];
+
+ let decrypted_len = match crypter.update(&text, result.as_mut_slice()) {
+ Ok(val) => val,
+ Err(err) => panic!("{}", err)
+ };
+
+ (&result[0..decrypted_len]).to_vec()
+}
+
+fn ecb_128_encrypt(key: &[u8], text: &[u8]) -> Vec<u8> {
+ ecb_128_crypt(Mode::Encrypt, key, text)
+}
+
+fn ecb_128_decrypt(key: &[u8], text: &[u8]) -> Vec<u8> {
+ ecb_128_crypt(Mode::Decrypt, key, text)
+}
+
+fn cbc_128_encrypt(key: &[u8], text: &[u8], iv: Vec<u8>) -> Vec<u8> {
+ let mut iv = iv;
+ let mut ciphertext = Vec::with_capacity(text.len());
+
+ for block in text.chunks(16) {
+ let xored = fixed_xor(iv, block.to_vec());
+ let encrypted = ecb_128_encrypt(key, xored.as_slice());
+
+ ciphertext.extend(encrypted.clone());
+ iv = encrypted;
+ }
+
+ ciphertext
+}
+
+fn cbc_128_decrypt(key: &[u8], text: &[u8], iv: Vec<u8>) -> Vec<u8> {
+ let mut iv = iv;
+ let mut plain = Vec::with_capacity(text.len());
+
+ for block in text.chunks(16) {
+ let decrypted = ecb_128_decrypt(key, block);
+ plain.extend(fixed_xor(decrypted, iv));
+
+ iv = block.to_vec();
+ }
+
+ plain
+}
+
+fn main() {
+ let args = App::new("aes_cbc")
+ .version("0.1")
+ .about("AES ECB/CBC tools")
+ .arg(Arg::with_name("key")
+ .short("k")
+ .long("key")
+ .value_name("KEY")
+ .takes_value(true)
+ .required(true))
+ .arg(Arg::with_name("mode")
+ .short("e")
+ .long("encrypt")
+ .help("encrypt (instead of decrypt)"))
+ .arg(Arg::with_name("iv")
+ .short("i")
+ .long("iv")
+ .value_name("INIT")
+ .takes_value(true)
+ .help("initial value"))
+ .get_matches();
+
+ let mut buffer = String::new();
+
+ io::stdin().read_to_string(&mut buffer).expect("aes_cbc");
+
+ let decoded = match base64::decode(&buffer) {
+ Ok(val) => val,
+ Err(err) => panic!("{}", err)
+ };
+
+ let mode = match args.occurrences_of("mode") {
+ 0 => Mode::Decrypt,
+ _ => Mode::Encrypt,
+ };
+
+ let key = match args.value_of("key") {
+ Some(text) =>
+ if text.len() == 16 {
+ text.as_bytes()
+ } else {
+ panic!("invalid key length!");
+ },
+ None => panic!("no key provided.")
+ };
+
+ let iv = match args.value_of("iv") {
+ Some(text) => text.as_bytes().to_vec(),
+ None => (&[0u8; 16]).to_vec(),
+ };
+
+ let output = match mode {
+ Mode::Decrypt => cbc_128_decrypt(&decoded[..], key, iv),
+ Mode::Encrypt => cbc_128_encrypt(&decoded[..], key, iv),
+ };
+
+ match mode {
+ Mode::Decrypt => println!("{}", String::from_utf8_lossy(&output)),
+ Mode::Encrypt => println!("{}", base64::encode(&output)),
+ };
+}
+