From b57378bbae70973575cae9cd4eba65cc883ba30f Mon Sep 17 00:00:00 2001 From: moparisthebest Date: Tue, 8 Aug 2017 00:33:17 -0400 Subject: [PATCH] Add rust implementation and test/benchmark script --- Cargo.lock | 130 +++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 10 ++++ src/main.rs | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test.sh | 19 +++++++ 4 files changed, 308 insertions(+) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs create mode 100755 test.sh diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c5889da --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,130 @@ +[root] +name = "image_downloader" +version = "0.1.0" +dependencies = [ + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "conv" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "custom_derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "gcc" +version = "0.3.51" +source = "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 = "libc" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "magenta" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "magenta-sys" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rust-crypto" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "time" +version = "0.1.38" +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.29 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (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 bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" +"checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299" +"checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" +"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "8a014d9226c2cc402676fbe9ea2e15dd5222cd1dd57f576b5b283178c944a264" +"checksum magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf0336886480e671965f794bc9b6fce88503563013d1bfb7a502c81fe3ac527" +"checksum magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40d014c7011ac470ae28e2f76a02bfea4a8480f73e701353b49ad7a8d75f4699" +"checksum rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb250fd207a4729c976794d03db689c9be1d634ab5a1c9da9492a13d8fecbcdf" +"checksum redox_syscall 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9309631a35303bffb47e397198e3668cb544fe8834cd3da2a744441e70e524" +"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" +"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/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d902c7f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "image_downloader" +version = "0.1.0" +authors = ["moparisthebest "] + +[dependencies] +rust-crypto = "0.2.36" +rustc-serialize = "0.3.24" +#rand = "^0.3" +#ring = "0.11.0" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..055ea9a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,149 @@ +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate crypto; +extern crate rustc_serialize; + +use std::env; +use std::io::{self, Write, Read, stdin}; + +use crypto::aes; + +use rustc_serialize::hex::*; +use std::iter::repeat; + +use crypto::aes_gcm::*; +use crypto::aead::{AeadEncryptor,AeadDecryptor}; + +// Encrypt a buffer with the given key and iv using +// AES-256/CBC/Pkcs encryption. +fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Vec { + + // Create an encryptor instance of the best performing + // type available for the platform. + let aad: [u8; 0] = []; + let mut encryptor = AesGcm::new( + aes::KeySize::KeySize256, + key, + iv, + &aad + ); + + let mut out: Vec = repeat(0).take(data.len()).collect(); + let mut out_tag: Vec = repeat(0).take(16).collect(); + + encryptor.encrypt(&data[..], &mut out[..],&mut out_tag[..]); + + out.extend_from_slice(&out_tag); + return out +} + +// Decrypts a buffer with the given key and iv using +// AES-256/CBC/Pkcs encryption. +// +// This function is very similar to encrypt(), so, please reference +// comments in that function. In non-example code, if desired, it is possible to +// share much of the implementation using closures to hide the operation +// being performed. However, such code would make this example less clear. +fn decrypt(encrypted_data: &[u8], key: &[u8], iv: &[u8]) -> Result, &'static str> { + // Create an decryptor instance of the best performing + // type available for the platform. + + let aad: [u8; 0] = []; + let mut decryptor = AesGcm::new( + aes::KeySize::KeySize256, + key, + iv, + &aad + ); + + let out_len = encrypted_data.len() - 16; + let mut out: Vec = repeat(0).take(out_len).collect(); + + let result = decryptor.decrypt(&encrypted_data[0..out_len], &mut out[..], &encrypted_data[out_len..]); + if result { + Ok(out) + } else { + Err("decryption failed") + } +} + +/* + +extern crate ring; +use ring::aead::*; + +fn encrypt_ring(data: &[u8], key: &[u8], iv: &[u8]) -> Vec { + + let sealing_key = SealingKey::new(&AES_256_GCM, key).unwrap(); + let additional_data: [u8; 0] = []; + + let mut out: Vec = repeat(0).take(data.len() + 16).collect(); + + let output_size = seal_in_place(&sealing_key, + &iv, + &additional_data, + &mut out, + 16) + .unwrap(); + + return out +} + +*/ + +fn main() { + let args: Vec = env::args().collect(); + + let mut enc= false; + + if args.len() < 2 || args.len() > 3 { + panic!("Usage: {} [enc]", args[0]); + } else if args.len() == 3 { + match &args[2][..] { + "enc" => { enc = true; } + _ => panic!("Usage: {} [enc]", args[0]) + } + } + + //let message = "boba"; + //println!("message: '{}' hex: '{}'", message, message.as_bytes().to_hex()); + //let key_iv = "e910dd93e4bbf608957fcb25e08dd8e049e41b7b9d453b2b019bffe5726b1669bca9f40b5fdc0917cd84426df78f8236"; + //let key_iv = "e910dd93e4bbf608957fcb2549e41b7b9d453b2b019bffe5726b1669bca9f40b5fdc0917cd84426df78f8236"; + let key_iv = &args[1]; + + let mut key_iv = key_iv.from_hex().expect("Invalid hex for key"); + + //let iv_len = if key_iv.len() == 48 { 16 } else { 12 }; + let iv_len = match key_iv.len() { + // todo: rust-crypto does not support non-12-byte nonce/iv 48 => 16, + 44 => 12, + _ => panic!("only key lengths of 44 bytes are supported") + }; + let (iv, key) = key_iv.split_at_mut(iv_len); + //let (iv, key) = key_iv.split_at_mut(if key_iv.len() == 48 { 16 } else { 12 }); // borrow checker explodes + + //println!("key: '{:?}' iv: '{:?}'", key, iv); + //println!("key: '{}' iv: '{}'", key.to_hex(), iv.to_hex()); + //let data = message.as_bytes(); + let mut data : Vec = Vec::new(); + stdin().read_to_end(& mut data).expect("error reading from stdin"); + + let data : Vec = if enc { + encrypt(&data, &key, &iv) + } else { + decrypt(&data, &key, &iv).expect("error during decryption") + }; + + // aesgcm bd92a7b359f5d9a359c6bbda242b1f4cb2f4c8d9 + // rust bd92a7b359f5d9a359c6bbda242b1f4cb2f4c8d9 + // ring dffdc5d2460bc181e2a34d139e72b32c0985018a + + //println!("message: '{}' encrypted: '{}'", message, encrypted_data.to_hex()); + + //println!("decrypted: {:?}", String::from_utf8(decrypted_data).unwrap()); + io::stdout().write(&data).expect("error writing to stdout"); +} diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..2ca539e --- /dev/null +++ b/test.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# try different size files to encrypt/decrypt +#dd if=/dev/urandom bs=1M count=100 of=/dev/shm/randombytes + +# compile C and rust code this way +#gcc aesgcm.c -lcrypto -O3 -o aesgcm +#cargo build --release + +export key=e910dd93e4bbf608957fcb2549e41b7b9d453b2b019bffe5726b1669bca9f40b5fdc0917cd84426df78f8236 + +test () { + bin=$1 + #tee >(md5sum - 1>&2) - < /dev/shm/randombytes | $bin $key enc | $bin $key | md5sum - + $bin $key enc < /dev/shm/randombytes | $bin $key &>/dev/null +} + +time test ./aesgcm +time test ./target/release/image_downloader