extern crate nettle;
extern crate rand;
use nettle::aead::{Eax, Gcm};
use nettle::cipher::{Aes128, Twofish};
use nettle::hash::{Hash, Sha224, Sha256};
use nettle::mac::Hmac;
use nettle::mode::{Cbc, Cfb};
use nettle::Aead;
use nettle::Mac;
use nettle::Mode;
struct Fubar {
foo: Foo,
bar: Bar,
baz: Baz,
}
impl Default for Fubar {
fn default() -> Fubar {
Fubar { foo: Foo::default(), bar: Bar::default(), baz: Baz::default() }
}
}
impl Fubar {
pub fn produce_hash(&self) -> Vec<u8> {
let mut h = self.init_hash();
self.foo.hash(&mut h);
self.bar.hash(&mut h);
self.baz.hash(&mut h);
let mut g = h.clone();
self.foo.hash(&mut g);
self.bar.hash(&mut g);
self.baz.hash(&mut g);
let mut ret = vec![0u8; h.digest_size()];
h.digest(&mut ret);
ret
}
pub fn produce_mac(&self) -> Vec<u8> {
let mut h = self.init_mac();
self.foo.mac(&mut h);
self.bar.mac(&mut h);
self.baz.mac(&mut h);
let mut ret = vec![0u8; h.mac_size()];
h.digest(&mut ret).unwrap();
ret
}
fn init_hash(&self) -> Box<Hash> {
if rand::random::<bool>() {
Box::new(Sha224::default())
} else {
Box::new(Sha256::default())
}
}
fn init_mac(&self) -> Box<Mac> {
if rand::random::<bool>() {
Box::new(Hmac::<Sha224>::with_key(&b"123"[..]))
} else {
Box::new(Hmac::<Sha256>::with_key(&b"123"[..]))
}
}
fn init_cipher(&self) -> Box<Mode> {
if rand::random::<bool>() {
Box::new(Cbc::<Aes128>::with_encrypt_key(&b"123"[..]).unwrap())
} else {
Box::new(Cfb::<Twofish>::with_encrypt_key(&b"123"[..]).unwrap())
}
}
fn init_aead(&self) -> Box<Aead> {
if rand::random::<bool>() {
Box::new(
Gcm::<Aes128>::with_key_and_nonce(&b"123"[..], &b"123"[..])
.unwrap(),
)
} else {
Box::new(
Eax::<Twofish>::with_key_and_nonce(&b"123"[..], &b"123"[..])
.unwrap(),
)
}
}
}
struct Foo {
num_foos: usize,
}
impl Default for Foo {
fn default() -> Foo {
Foo { num_foos: 42 }
}
}
impl Foo {
pub fn hash<H: AsMut<Hash>>(&self, h: &mut H) {
h.as_mut().update(format!("{}", self.num_foos).as_bytes());
}
pub fn mac<H: AsMut<Mac>>(&self, h: &mut H) {
h.as_mut().update(format!("{}", self.num_foos).as_bytes());
}
}
struct Bar {
bar: &'static str,
}
impl Default for Bar {
fn default() -> Bar {
Bar { bar: "Hallo, I bims bar vong foo her" }
}
}
impl Bar {
pub fn hash<H: AsMut<Hash>>(&self, h: &mut H) {
h.as_mut().update(self.bar.as_bytes());
}
pub fn mac<H: AsMut<Mac>>(&self, h: &mut H) {
h.as_mut().update(self.bar.as_bytes());
}
}
enum Baz {
One,
Two,
Three,
}
impl Default for Baz {
fn default() -> Baz {
if rand::random::<bool>() {
if rand::random::<bool>() {
Baz::One
} else {
Baz::Two
}
} else {
Baz::Three
}
}
}
impl Baz {
pub fn hash<H: AsMut<Hash>>(&self, h: &mut H) {
match self {
&Baz::One => h.as_mut().update(&b"Hello"[..]),
&Baz::Two => h.as_mut().update(&b"Hallo"[..]),
&Baz::Three => h.as_mut().update("こにちわ".as_bytes()),
}
}
pub fn mac<H: AsMut<Mac>>(&self, h: &mut H) {
match self {
&Baz::One => h.as_mut().update(&b"Hello"[..]),
&Baz::Two => h.as_mut().update(&b"Hallo"[..]),
&Baz::Three => h.as_mut().update("こにちわ".as_bytes()),
}
}
}
fn main() {
let fubar = Fubar::default();
fubar.init_aead();
fubar.init_cipher();
println!("Fubar hash: {:?}", fubar.produce_hash());
println!("Fubar mac: {:?}", fubar.produce_mac());
}