digest/block_api.rs
1//! Low-level traits operating on blocks and wrappers around them.
2//!
3//! Usage of traits in this module in user code is discouraged. Instead use
4//! core algorithm wrapped by the wrapper types, which implement the
5//! higher-level traits.
6use crate::{Digest, HashMarker, InvalidOutputSize};
7
8pub use block_buffer::{Eager, Lazy};
9pub use common::{AlgorithmName, Block, BlockSizeUser, OutputSizeUser, Reset};
10
11use block_buffer::{BlockBuffer, BlockSizes, BufferKind};
12use common::Output;
13
14mod ct_variable;
15pub use ct_variable::CtOutWrapper;
16
17/// Buffer type used by type which implements [`BufferKindUser`].
18pub type Buffer<S> =
19 BlockBuffer<<S as BlockSizeUser>::BlockSize, <S as BufferKindUser>::BufferKind>;
20
21/// Types which consume data in blocks.
22pub trait UpdateCore: BlockSizeUser {
23 /// Update state using the provided data blocks.
24 fn update_blocks(&mut self, blocks: &[Block<Self>]);
25}
26
27/// Sub-trait of [`BlockSizeUser`] implemented if `BlockSize` is
28/// bigger than `U0` and smaller than `U256`.
29///
30/// This trait relies on the hack suggested [here][0] to work around
31/// the long standing Rust issue regarding non-propagation of `where` bounds.
32///
33/// [0]: https://github.com/rust-lang/rust/issues/20671#issuecomment-1905186183
34pub trait SmallBlockSizeUser:
35 BlockSizeUser<BlockSize = <Self as SmallBlockSizeUser>::_BlockSize>
36{
37 /// Helper associated type equal to `<Self as BlockSizeUser>::BlockSize`.
38 type _BlockSize: BlockSizes;
39}
40
41impl<T: BlockSizeUser> SmallBlockSizeUser for T
42where
43 T::BlockSize: BlockSizes,
44{
45 type _BlockSize = T::BlockSize;
46}
47
48/// Types which use [`BlockBuffer`] functionality.
49pub trait BufferKindUser: SmallBlockSizeUser {
50 /// Block buffer kind over which type operates.
51 type BufferKind: BufferKind;
52}
53
54/// Trait implemented by eager hashes which expose their block-level core.
55pub trait EagerHash: SmallBlockSizeUser + Digest + Clone {
56 /// Block-level core type of the hash.
57 type Core: HashMarker
58 + UpdateCore
59 + FixedOutputCore
60 + SmallBlockSizeUser<_BlockSize = <Self as SmallBlockSizeUser>::_BlockSize>
61 + BufferKindUser<BufferKind = Eager>
62 + Default
63 + Clone;
64}
65
66impl<T> EagerHash for T
67where
68 T: CoreProxy + SmallBlockSizeUser + Digest + Clone,
69 <T as CoreProxy>::Core: HashMarker
70 + UpdateCore
71 + FixedOutputCore
72 + SmallBlockSizeUser<_BlockSize = <T as SmallBlockSizeUser>::_BlockSize>
73 + BufferKindUser<BufferKind = Eager>
74 + Default
75 + Clone,
76{
77 type Core = T::Core;
78}
79
80/// Core trait for hash functions with fixed output size.
81pub trait FixedOutputCore: UpdateCore + BufferKindUser + OutputSizeUser {
82 /// Finalize state using remaining data stored in the provided block buffer,
83 /// write result into provided array and leave `self` in a dirty state.
84 fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>);
85}
86
87/// Core trait for hash functions with extendable (XOF) output size.
88pub trait ExtendableOutputCore: UpdateCore + BufferKindUser {
89 /// XOF reader core state.
90 type ReaderCore: XofReaderCore;
91
92 /// Retrieve XOF reader using remaining data stored in the block buffer
93 /// and leave hasher in a dirty state.
94 fn finalize_xof_core(&mut self, buffer: &mut Buffer<Self>) -> Self::ReaderCore;
95}
96
97/// Core reader trait for extendable-output function (XOF) result.
98pub trait XofReaderCore: BlockSizeUser {
99 /// Read next XOF block.
100 fn read_block(&mut self) -> Block<Self>;
101}
102
103/// Core trait for hash functions with variable output size.
104///
105/// Maximum output size is equal to [`OutputSizeUser::OutputSize`].
106/// Users are expected to truncate result returned by the
107/// [`finalize_variable_core`] to `output_size` passed to the [`new`] method
108/// during construction. Truncation side is defined by the [`TRUNC_SIDE`]
109/// associated constant.
110///
111/// [`finalize_variable_core`]: VariableOutputCore::finalize_variable_core
112/// [`new`]: VariableOutputCore::new
113/// [`TRUNC_SIDE`]: VariableOutputCore::TRUNC_SIDE
114pub trait VariableOutputCore: UpdateCore + OutputSizeUser + BufferKindUser + Sized {
115 /// Side which should be used in a truncated result.
116 const TRUNC_SIDE: TruncSide;
117
118 /// Initialize hasher state for given output size.
119 ///
120 /// # Errors
121 /// Returns [`InvalidOutputSize`] if `output_size` is not valid for
122 /// the algorithm, e.g. if it's bigger than the [`OutputSize`]
123 /// associated type.
124 ///
125 /// [`OutputSize`]: OutputSizeUser::OutputSize
126 fn new(output_size: usize) -> Result<Self, InvalidOutputSize>;
127
128 /// Finalize hasher and write full hashing result into the `out` buffer.
129 ///
130 /// The result must be truncated to `output_size` used during hasher
131 /// construction. Truncation side is defined by the [`TRUNC_SIDE`]
132 /// associated constant.
133 ///
134 /// [`TRUNC_SIDE`]: VariableOutputCore::TRUNC_SIDE
135 fn finalize_variable_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>);
136}
137
138/// Trait adding customization string to hash functions with variable output.
139pub trait VariableOutputCoreCustomized: VariableOutputCore {
140 /// Create new hasher instance with the given customization string and output size.
141 fn new_customized(customization: &[u8], output_size: usize) -> Self;
142}
143
144/// Type which used for defining truncation side in the [`VariableOutputCore`]
145/// trait.
146#[derive(Copy, Clone, Debug)]
147pub enum TruncSide {
148 /// Truncate left side, i.e. `&out[..n]`.
149 Left,
150 /// Truncate right side, i.e. `&out[m..]`.
151 Right,
152}
153
154/// A proxy trait to the core block-level type.
155pub trait CoreProxy {
156 /// Core block-level type.
157 type Core: BufferKindUser;
158
159 /// Create `Self` from core and buffer.
160 fn compose(core: Self::Core, buffer: Buffer<Self::Core>) -> Self;
161 /// Decompose `self` into core and buffer.
162 fn decompose(self) -> (Self::Core, Buffer<Self::Core>);
163}