digest/
lib.rs

1//! This crate provides traits which describe functionality of cryptographic hash
2//! functions and Message Authentication algorithms.
3//!
4//! Traits in this repository are organized into the following levels:
5//!
6//! - **High-level convenience traits**: [`Digest`], [`DynDigest`], [`Mac`].
7//!   Wrappers around lower-level traits for most common use-cases. Users should
8//!   usually prefer using these traits.
9//! - **Mid-level traits**: [`Update`], [`FixedOutput`], [`FixedOutputReset`],
10//!   [`ExtendableOutput`], [`ExtendableOutputReset`], [`XofReader`],
11//!   [`VariableOutput`], [`Reset`], [`KeyInit`], and [`InnerInit`]. These
12//!   traits atomically describe available functionality of an algorithm.
13//! - **Marker traits**: [`HashMarker`], [`MacMarker`]. Used to distinguish
14//!   different algorithm classes.
15//! - **Low-level traits** defined in the [`block_api`] module. These traits
16//!   operate at a block-level and do not contain any built-in buffering.
17//!   They are intended to be implemented by low-level algorithm providers only.
18//!   Usually they should not be used in application-level code.
19//!
20//! Additionally hash functions implement traits from the standard library:
21//! [`Default`] and [`Clone`].
22//!
23//! This crate does not provide any implementations of the `io::Read/Write` traits,
24//! see the [`digest-io`] crate for `std::io`-compatibility wrappers.
25//!
26//! [`digest-io`]: https://docs.rs/digest-io
27
28#![no_std]
29#![cfg_attr(docsrs, feature(doc_auto_cfg))]
30#![forbid(unsafe_code)]
31#![doc(
32    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
33    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
34)]
35#![warn(missing_docs, rust_2018_idioms, missing_debug_implementations)]
36
37#[cfg(feature = "alloc")]
38#[macro_use]
39extern crate alloc;
40
41#[cfg(feature = "rand_core")]
42pub use crypto_common::rand_core;
43
44#[cfg(feature = "zeroize")]
45pub use zeroize;
46
47#[cfg(feature = "alloc")]
48use alloc::boxed::Box;
49
50#[cfg(feature = "dev")]
51pub mod dev;
52
53#[cfg(feature = "block-api")]
54pub mod block_api;
55mod buffer_macros;
56mod digest;
57#[cfg(feature = "mac")]
58mod mac;
59mod xof_fixed;
60
61#[cfg(feature = "block-api")]
62pub use block_buffer;
63#[cfg(feature = "oid")]
64pub use const_oid;
65pub use crypto_common;
66
67#[cfg(feature = "const-oid")]
68pub use crate::digest::DynDigestWithOid;
69pub use crate::digest::{Digest, DynDigest, HashMarker};
70#[cfg(feature = "mac")]
71pub use crypto_common::{InnerInit, InvalidLength, Key, KeyInit};
72pub use crypto_common::{Output, OutputSizeUser, Reset, array, typenum, typenum::consts};
73#[cfg(feature = "mac")]
74pub use mac::{CtOutput, Mac, MacError, MacMarker};
75pub use xof_fixed::XofFixedWrapper;
76
77#[cfg(feature = "block-api")]
78#[deprecated(
79    since = "0.11.0",
80    note = "`digest::core_api` has been replaced by `digest::block_api`"
81)]
82pub use block_api as core_api;
83
84use core::fmt;
85use crypto_common::typenum::Unsigned;
86
87/// Types which consume data with byte granularity.
88pub trait Update {
89    /// Update state using the provided data.
90    fn update(&mut self, data: &[u8]);
91
92    /// Digest input data in a chained manner.
93    #[must_use]
94    fn chain(mut self, data: impl AsRef<[u8]>) -> Self
95    where
96        Self: Sized,
97    {
98        self.update(data.as_ref());
99        self
100    }
101}
102
103/// Trait for hash functions with fixed-size output.
104pub trait FixedOutput: Update + OutputSizeUser + Sized {
105    /// Consume value and write result into provided array.
106    fn finalize_into(self, out: &mut Output<Self>);
107
108    /// Retrieve result and consume the hasher instance.
109    #[inline]
110    fn finalize_fixed(self) -> Output<Self> {
111        let mut out = Default::default();
112        self.finalize_into(&mut out);
113        out
114    }
115}
116
117/// Trait for hash functions with fixed-size output able to reset themselves.
118pub trait FixedOutputReset: FixedOutput + Reset {
119    /// Write result into provided array and reset the hasher state.
120    fn finalize_into_reset(&mut self, out: &mut Output<Self>);
121
122    /// Retrieve result and reset the hasher state.
123    #[inline]
124    fn finalize_fixed_reset(&mut self) -> Output<Self> {
125        let mut out = Default::default();
126        self.finalize_into_reset(&mut out);
127        out
128    }
129}
130
131/// Trait for reader types which are used to extract extendable output
132/// from a XOF (extendable-output function) result.
133pub trait XofReader {
134    /// Read output into the `buffer`. Can be called an unlimited number of times.
135    fn read(&mut self, buffer: &mut [u8]);
136
137    /// Read output into a boxed slice of the specified size.
138    ///
139    /// Can be called an unlimited number of times in combination with `read`.
140    ///
141    /// `Box<[u8]>` is used instead of `Vec<u8>` to save stack space, since
142    /// they have size of 2 and 3 words respectively.
143    #[cfg(feature = "alloc")]
144    fn read_boxed(&mut self, n: usize) -> Box<[u8]> {
145        let mut buf = vec![0u8; n].into_boxed_slice();
146        self.read(&mut buf);
147        buf
148    }
149}
150
151/// Trait for hash functions with extendable-output (XOF).
152pub trait ExtendableOutput: Sized + Update {
153    /// Reader
154    type Reader: XofReader;
155
156    /// Retrieve XOF reader and consume hasher instance.
157    fn finalize_xof(self) -> Self::Reader;
158
159    /// Finalize XOF and write result into `out`.
160    fn finalize_xof_into(self, out: &mut [u8]) {
161        self.finalize_xof().read(out);
162    }
163
164    /// Compute hash of `data` and write it into `output`.
165    fn digest_xof(input: impl AsRef<[u8]>, output: &mut [u8])
166    where
167        Self: Default,
168    {
169        let mut hasher = Self::default();
170        hasher.update(input.as_ref());
171        hasher.finalize_xof().read(output);
172    }
173
174    /// Retrieve result into a boxed slice of the specified size and consume
175    /// the hasher.
176    ///
177    /// `Box<[u8]>` is used instead of `Vec<u8>` to save stack space, since
178    /// they have size of 2 and 3 words respectively.
179    #[cfg(feature = "alloc")]
180    fn finalize_boxed(self, output_size: usize) -> Box<[u8]> {
181        let mut buf = vec![0u8; output_size].into_boxed_slice();
182        self.finalize_xof().read(&mut buf);
183        buf
184    }
185}
186
187/// Trait for hash functions with extendable-output (XOF) able to reset themselves.
188pub trait ExtendableOutputReset: ExtendableOutput + Reset {
189    /// Retrieve XOF reader and reset hasher instance state.
190    fn finalize_xof_reset(&mut self) -> Self::Reader;
191
192    /// Finalize XOF, write result into `out`, and reset the hasher state.
193    fn finalize_xof_reset_into(&mut self, out: &mut [u8]) {
194        self.finalize_xof_reset().read(out);
195    }
196
197    /// Retrieve result into a boxed slice of the specified size and reset
198    /// the hasher state.
199    ///
200    /// `Box<[u8]>` is used instead of `Vec<u8>` to save stack space, since
201    /// they have size of 2 and 3 words respectively.
202    #[cfg(feature = "alloc")]
203    fn finalize_boxed_reset(&mut self, output_size: usize) -> Box<[u8]> {
204        let mut buf = vec![0u8; output_size].into_boxed_slice();
205        self.finalize_xof_reset().read(&mut buf);
206        buf
207    }
208}
209
210/// Trait for hash functions with variable-size output.
211pub trait VariableOutput: Sized + Update {
212    /// Maximum size of output hash in bytes.
213    const MAX_OUTPUT_SIZE: usize;
214
215    /// Create new hasher instance with the given output size in bytes.
216    ///
217    /// It will return `Err(InvalidOutputSize)` in case if hasher can not return
218    /// hash of the specified output size.
219    fn new(output_size: usize) -> Result<Self, InvalidOutputSize>;
220
221    /// Get output size in bytes of the hasher instance provided to the `new` method
222    fn output_size(&self) -> usize;
223
224    /// Write result into the output buffer.
225    ///
226    /// Returns `Err(InvalidOutputSize)` if `out` size is not equal to
227    /// `self.output_size()`.
228    fn finalize_variable(self, out: &mut [u8]) -> Result<(), InvalidBufferSize>;
229
230    /// Compute hash of `data` and write it to `output`.
231    ///
232    /// Length of the output hash is determined by `output`. If `output` is
233    /// bigger than `Self::MAX_OUTPUT_SIZE`, this method returns
234    /// `InvalidOutputSize`.
235    fn digest_variable(
236        input: impl AsRef<[u8]>,
237        output: &mut [u8],
238    ) -> Result<(), InvalidOutputSize> {
239        let mut hasher = Self::new(output.len())?;
240        hasher.update(input.as_ref());
241        hasher
242            .finalize_variable(output)
243            .map_err(|_| InvalidOutputSize)
244    }
245
246    /// Retrieve result into a boxed slice and consume hasher.
247    ///
248    /// `Box<[u8]>` is used instead of `Vec<u8>` to save stack space, since
249    /// they have size of 2 and 3 words respectively.
250    #[cfg(feature = "alloc")]
251    fn finalize_boxed(self) -> Box<[u8]> {
252        let n = self.output_size();
253        let mut buf = vec![0u8; n].into_boxed_slice();
254        self.finalize_variable(&mut buf)
255            .expect("buf length is equal to output_size");
256        buf
257    }
258}
259
260/// Trait for hash functions with variable-size output able to reset themselves.
261pub trait VariableOutputReset: VariableOutput + Reset {
262    /// Write result into the output buffer and reset the hasher state.
263    ///
264    /// Returns `Err(InvalidOutputSize)` if `out` size is not equal to
265    /// `self.output_size()`.
266    fn finalize_variable_reset(&mut self, out: &mut [u8]) -> Result<(), InvalidBufferSize>;
267
268    /// Retrieve result into a boxed slice and reset the hasher state.
269    ///
270    /// `Box<[u8]>` is used instead of `Vec<u8>` to save stack space, since
271    /// they have size of 2 and 3 words respectively.
272    #[cfg(feature = "alloc")]
273    fn finalize_boxed_reset(&mut self) -> Box<[u8]> {
274        let n = self.output_size();
275        let mut buf = vec![0u8; n].into_boxed_slice();
276        self.finalize_variable_reset(&mut buf)
277            .expect("buf length is equal to output_size");
278        buf
279    }
280}
281
282/// Trait for hash functions with customization string for domain separation.
283pub trait CustomizedInit: Sized {
284    /// Create new hasher instance with the given customization string.
285    fn new_customized(customization: &[u8]) -> Self;
286}
287
288/// Trait adding customization string to hash functions with variable output.
289pub trait VarOutputCustomized: Sized {
290    /// Create new hasher instance with the given customization string and output size.
291    fn new_customized(customization: &[u8], output_size: usize) -> Self;
292}
293
294/// Types with a certain collision resistance.
295pub trait CollisionResistance {
296    /// Collision resistance in bytes. This applies to an output size of `CollisionResistance * 2`.
297    /// The collision resistance with a smaller output size is not defined by this trait and is at
298    /// least the given collision resistance with a bigger output.
299    type CollisionResistance: Unsigned;
300}
301
302/// The error type used in variable hash traits.
303#[derive(Clone, Copy, Debug, Default)]
304pub struct InvalidOutputSize;
305
306impl fmt::Display for InvalidOutputSize {
307    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
308        f.write_str("invalid output size")
309    }
310}
311
312impl core::error::Error for InvalidOutputSize {}
313
314/// Buffer length is not equal to hash output size.
315#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
316pub struct InvalidBufferSize;
317
318impl fmt::Display for InvalidBufferSize {
319    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
320        f.write_str("invalid buffer length")
321    }
322}
323
324impl core::error::Error for InvalidBufferSize {}