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
use {Hash, ParameterBlock, compress, IV}; use slice_ext::{SliceExt}; #[derive(Clone, Debug)] pub struct Blake2b { hash: [u64; 8], counter: (u64, u64), len: usize } impl Blake2b { pub fn new(len: usize) -> Self { Self::with_parameter_block(len, ParameterBlock::new().set_digest_len(len as u8).set_fanout(1).set_max_depth(1)) } pub fn with_parameter_block(len: usize, parameter_block: ParameterBlock) -> Self { assert!(len >= 1 && len <= 64, "len must be >= 1 and <= 64"); let mut hash = parameter_block.0; for (a, b) in hash.iter_mut().zip(IV.iter()) { *a ^= *b; } Blake2b { hash: hash, counter: (0, 0), len: len } } pub fn len(&self) -> usize { self.len } pub fn update(&mut self, block: &[u64; 16]) { self.add_counter(128); compress(block, &mut self.hash, self.counter, (0, 0)); } pub fn finish(mut self, block: &[u64; 16], len: usize) -> Hash { assert!(len <= 128); debug_assert!(block.as_bytes()[len..].iter().all(|&i| i == 0)); self.add_counter(len as u64); compress(block, &mut self.hash, self.counter, (!0, 0)); Hash::new(self.hash, self.len) } fn add_counter(&mut self, v: u64) { debug_assert!(v <= 128); let (v, b) = self.counter.0.overflowing_add(v); self.counter.0 = v; if b { self.counter.1 = self.counter.1.checked_add(1).expect("blake2b counter overflowed"); } } } impl Default for Blake2b { fn default() -> Self { Self::new(64) } }