nettle 3.0.0

Rust bindings for the Nettle cryptographic library
extern crate nettle;
extern crate rand;

use nettle::hash::{Hash,Sha224,Sha256};
use nettle::Mac;
use nettle::mac::Hmac;
use nettle::Mode;
use nettle::cipher::{Aes128,Twofish};
use nettle::mode::{Cfb,Cbc};
use nettle::Aead;
use nettle::aead::{Gcm,Eax};

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);

        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());
}