ab_blake3/
single_chunk.rs1#[cfg(test)]
7mod tests;
8
9use crate::platform::{le_bytes_from_words_32, words_from_le_bytes_32};
10use crate::{
11 BLOCK_LEN, CHUNK_END, CHUNK_LEN, CHUNK_START, CVWords, DERIVE_KEY_CONTEXT, DERIVE_KEY_MATERIAL,
12 IV, KEY_LEN, KEYED_HASH, OUT_LEN, ROOT,
13};
14use blake3::platform::Platform;
15
16#[inline(always)]
18fn hash_chunk(input: &[u8], key: CVWords, flags: u8) -> Option<[u8; OUT_LEN]> {
19 if input.len() > CHUNK_LEN {
21 return None;
22 }
23
24 let mut cv = key;
25 let platform = Platform::detect();
26 let (blocks, remainder) = input.as_chunks();
27 let num_blocks = blocks.len() + (!remainder.is_empty()) as usize;
28
29 for (block_index, block) in blocks.iter().enumerate() {
30 let mut block_flags = flags;
31 if block_index == 0 {
32 block_flags |= CHUNK_START;
33 }
34 if block_index + 1 == num_blocks {
35 block_flags |= CHUNK_END | ROOT;
36 }
37
38 platform.compress_in_place(&mut cv, block, BLOCK_LEN as u8, 0, block_flags);
39 }
40
41 if !remainder.is_empty() || num_blocks == 0 {
43 let mut block_flags = flags | CHUNK_END | ROOT;
44 if num_blocks <= 1 {
45 block_flags |= CHUNK_START;
46 }
47
48 let mut buf = [0; BLOCK_LEN];
49 buf[..remainder.len()].copy_from_slice(remainder);
50 platform.compress_in_place(&mut cv, &buf, remainder.len() as u8, 0, block_flags);
51 }
52
53 Some(*le_bytes_from_words_32(&cv))
54}
55
56#[inline]
60#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
61pub fn single_chunk_hash(input: &[u8]) -> Option<[u8; OUT_LEN]> {
62 hash_chunk(input, *IV, 0)
63}
64
65#[inline]
69#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
70pub fn single_chunk_keyed_hash(key: &[u8; KEY_LEN], input: &[u8]) -> Option<[u8; OUT_LEN]> {
71 let key_words = words_from_le_bytes_32(key);
72 hash_chunk(input, key_words, KEYED_HASH)
73}
74
75#[inline]
79#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
80pub fn single_chunk_derive_key(context: &str, key_material: &[u8]) -> Option<[u8; OUT_LEN]> {
81 let context_key = hash_chunk(context.as_bytes(), *IV, DERIVE_KEY_CONTEXT)?;
82 let context_key_words = words_from_le_bytes_32(&context_key);
83 hash_chunk(key_material, context_key_words, DERIVE_KEY_MATERIAL)
84}