ab_blake3/
single_block.rs1#[cfg(test)]
7mod tests;
8
9use crate::platform::{le_bytes_from_words_32, words_from_le_bytes_32};
10use crate::{
11 portable, BlockWords, CVWords, BLOCK_LEN, CHUNK_END, CHUNK_START, DERIVE_KEY_CONTEXT,
12 DERIVE_KEY_MATERIAL, IV, KEYED_HASH, KEY_LEN, OUT_LEN, ROOT,
13};
14use blake3::platform::Platform;
15
16#[inline(always)]
18fn hash_block(input: &[u8], key: CVWords, flags: u8) -> Option<[u8; OUT_LEN]> {
19 if input.len() > BLOCK_LEN {
21 return None;
22 }
23
24 let mut cv = key;
25
26 let mut block = [0; BLOCK_LEN];
27 block[..input.len()].copy_from_slice(input);
28 Platform::detect().compress_in_place(
29 &mut cv,
30 &block,
31 input.len() as u8,
32 0,
33 flags | CHUNK_START | CHUNK_END | ROOT,
34 );
35
36 Some(*le_bytes_from_words_32(&cv))
37}
38
39#[inline]
43#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
44pub fn single_block_hash(input: &[u8]) -> Option<[u8; OUT_LEN]> {
45 hash_block(input, *IV, 0)
46}
47
48#[inline]
52#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
53pub fn single_block_keyed_hash(key: &[u8; KEY_LEN], input: &[u8]) -> Option<[u8; OUT_LEN]> {
54 let key_words = words_from_le_bytes_32(key);
55 hash_block(input, key_words, KEYED_HASH)
56}
57
58#[inline]
62#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
63pub fn single_block_derive_key(context: &str, key_material: &[u8]) -> Option<[u8; OUT_LEN]> {
64 let context_key = hash_block(context.as_bytes(), *IV, DERIVE_KEY_CONTEXT)?;
65 let context_key_words = words_from_le_bytes_32(&context_key);
66 hash_block(key_material, context_key_words, DERIVE_KEY_MATERIAL)
67}
68
69#[inline]
84#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
85pub fn single_block_hash_portable_words(input: &BlockWords, num_bytes: u32) -> CVWords {
86 let mut cv = *IV;
87
88 portable::compress_in_place(
89 &mut cv,
90 input,
91 num_bytes,
92 0,
93 (CHUNK_START | CHUNK_END | ROOT) as u32,
94 );
95
96 cv
97}