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
use core::cmp::{min}; use {Hash, ParameterBlock}; use slice_ext::{SliceExt, zero_bytes}; use unbuffered; #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] pub struct Blake2b { blake2b: unbuffered::Blake2b, buffer: [u64; 16], buf_len: usize } impl Blake2b { pub fn new(len: usize) -> Self { Self::keyed(len, &[]) } pub fn keyed(len: usize, key: &[u8]) -> Self { Self::with_parameter_block_keyed(len, key, ParameterBlock::new().set_digest_len(len as u8).set_key_len(key.len() as u8).set_fanout(1).set_max_depth(1)) } pub fn with_parameter_block(len: usize, parameter_block: ParameterBlock) -> Self { Self::with_parameter_block_keyed(len, &[], parameter_block) } pub fn with_parameter_block_keyed(len: usize, key: &[u8], parameter_block: ParameterBlock) -> Self { let mut blake2b = Blake2b { blake2b: unbuffered::Blake2b::with_parameter_block(len, parameter_block), buffer: [0; 16], buf_len: 0 }; if !key.is_empty() { blake2b.buffer.as_mut_bytes()[..key.len()].copy_from_slice(key); blake2b.buf_len = 128; } blake2b } pub fn len(&self) -> usize { self.blake2b.len() } pub fn update(&mut self, mut data: &[u8]) { while !data.is_empty() { if self.buf_len == 128 { self.blake2b.update(&self.buffer); self.buf_len = 0; } let len = min(128 - self.buf_len, data.len()); self.buffer.as_mut_bytes()[self.buf_len..self.buf_len + len].copy_from_slice(&data[..len]); self.buf_len += len; data = &data[len..]; } } pub fn finish(mut self) -> Hash { zero_bytes(&mut self.buffer.as_mut_bytes()[self.buf_len..]); self.blake2b.finish(&self.buffer, self.buf_len) } } impl Default for Blake2b { fn default() -> Self { Self::new(64) } }