1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
#![cfg_attr(not(feature = "std"), no_std)]

use blake2_rfc::blake2s::Blake2s;
use byteorder::{LittleEndian, ByteOrder};

pub const PERSONALIZATION: &'static [u8; 8] = b"__fawkes";

pub struct SeedboxBlake2 {
    salt: Option<[u8; 32]>,
    n_iter: u64,
    n_limb: usize,
    buff: [u8; 32],
}

impl SeedboxBlake2 {
    fn update(&mut self) {
        self.n_limb = 0;
        let mut h = Blake2s::with_params(32, &[], &[], PERSONALIZATION);
        let mut n_iter_bin = [0u8; 8];

        LittleEndian::write_u64(&mut n_iter_bin, self.n_iter);

        self.n_iter += 1;
        h.update(n_iter_bin.as_ref());
        if self.salt.is_some() {
            h.update(self.salt.unwrap().as_ref());
        }
        self.buff.as_mut().clone_from_slice(h.finalize().as_ref())
    }

    fn next_byte(&mut self) -> u8 {
        if self.n_limb == 32 {
            self.update();
        }

        let res = self.buff[self.n_limb];
        self.n_limb += 1;
        res
    }

}

pub trait SeedBox {
    fn fill_bytes(&mut self, dest: &mut [u8]);
    fn fill_limbs(&mut self, dest: &mut [u64]);
    fn new() -> Self;
    fn new_with_salt(salt: &[u8]) -> Self;
}

impl SeedBox for SeedboxBlake2 {
    fn new() -> Self {
        let mut res = SeedboxBlake2 {
            salt: None,
            n_iter: 0,
            n_limb: 8,
            buff: [0; 32],
        };
        res.update();
        res
    }

    fn new_with_salt(salt: &[u8]) -> Self {
        let mut h = Blake2s::new(32);
        let mut buff = [0u8; 32];
        h.update(salt);
        buff[..].clone_from_slice(h.finalize().as_ref());

        let mut res= SeedboxBlake2 {
            salt: Some(buff),
            n_iter: 0,
            n_limb: 8,
            buff: [0; 32],
        };
        res.update();
        res
    }
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        dest.iter_mut().for_each(|f| *f = self.next_byte());
    }

    fn fill_limbs(&mut self, dest: &mut [u64]) {
        let mut b = [0u8;8];

        dest.iter_mut().for_each(|f| {
            self.fill_bytes(&mut b);
            *f = LittleEndian::read_u64(&b);
        });
    }
}

pub trait SeedBoxGen<Out>: SeedBox {
    fn gen(&mut self) -> Out;
}

pub trait FromSeed<S:SeedBoxGen<Self>> : Sized {
    fn from_seed(seed: &[u8]) -> Self;
}

impl<Out, S> FromSeed<S> for Out where S:SeedBoxGen<Out> {
    fn from_seed(seed: &[u8]) -> Self {
        let mut sb = S::new_with_salt(seed);
        sb.gen()
    }
}