Coverage Report

Created: 2026-09-06 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/universal-hash-0.4.1/src/lib.rs
Line
Count
Source
1
//! Traits for [Universal Hash Functions].
2
//!
3
//! # About universal hashes
4
//!
5
//! Universal hash functions provide a "universal family" of possible
6
//! hash functions where a given member of a family is selected by a key.
7
//!
8
//! They are well suited to the purpose of "one time authenticators" for a
9
//! sequence of bytestring inputs, as their construction has a number of
10
//! desirable properties such as pairwise independence as well as amenability
11
//! to efficient implementations, particularly when implemented using SIMD
12
//! instructions.
13
//!
14
//! When combined with a cipher, such as in Galois/Counter Mode (GCM) or the
15
//! Salsa20 family AEAD constructions, they can provide the core functionality
16
//! for a Message Authentication Code (MAC).
17
//!
18
//! [Universal Hash Functions]: https://en.wikipedia.org/wiki/Universal_hashing
19
20
#![no_std]
21
#![forbid(unsafe_code)]
22
#![doc(
23
    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
24
    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
25
    html_root_url = "https://docs.rs/universal-hash/0.4.1"
26
)]
27
#![warn(missing_docs, rust_2018_idioms)]
28
29
#[cfg(feature = "std")]
30
extern crate std;
31
32
pub use generic_array::{self, typenum::consts};
33
34
use generic_array::typenum::Unsigned;
35
use generic_array::{ArrayLength, GenericArray};
36
use subtle::{Choice, ConstantTimeEq};
37
38
/// Keys to a [`UniversalHash`].
39
pub type Key<U> = GenericArray<u8, <U as NewUniversalHash>::KeySize>;
40
41
/// Blocks are inputs to a [`UniversalHash`].
42
pub type Block<U> = GenericArray<u8, <U as UniversalHash>::BlockSize>;
43
44
/// Instantiate a [`UniversalHash`] algorithm.
45
pub trait NewUniversalHash: Sized {
46
    /// Size of the key for the universal hash function.
47
    type KeySize: ArrayLength<u8>;
48
49
    /// Instantiate a universal hash function with the given key.
50
    fn new(key: &Key<Self>) -> Self;
51
}
52
53
/// The [`UniversalHash`] trait defines a generic interface for universal hash
54
/// functions.
55
pub trait UniversalHash: Clone {
56
    /// Size of the inputs to and outputs from the universal hash function
57
    type BlockSize: ArrayLength<u8>;
58
59
    /// Input a block into the universal hash function
60
    fn update(&mut self, block: &Block<Self>);
61
62
    /// Input data into the universal hash function. If the length of the
63
    /// data is not a multiple of the block size, the remaining data is
64
    /// padded with zeroes up to the `BlockSize`.
65
    ///
66
    /// This approach is frequently used by AEAD modes which use
67
    /// Message Authentication Codes (MACs) based on universal hashing.
68
452
    fn update_padded(&mut self, data: &[u8]) {
69
452
        let mut chunks = data.chunks_exact(Self::BlockSize::to_usize());
70
71
42.9k
        for chunk in &mut chunks {
72
42.5k
            self.update(GenericArray::from_slice(chunk));
73
42.5k
        }
74
75
452
        let rem = chunks.remainder();
76
77
452
        if !rem.is_empty() {
78
422
            let mut padded_block = GenericArray::default();
79
422
            padded_block[..rem.len()].copy_from_slice(rem);
80
422
            self.update(&padded_block);
81
422
        }
82
452
    }
83
84
    /// Reset [`UniversalHash`] instance.
85
    fn reset(&mut self);
86
87
    /// Obtain the [`Output`] of a [`UniversalHash`] function and consume it.
88
    fn finalize(self) -> Output<Self>;
89
90
    /// Obtain the [`Output`] of a [`UniversalHash`] computation and reset it back
91
    /// to its initial state.
92
    fn finalize_reset(&mut self) -> Output<Self> {
93
        let res = self.clone().finalize();
94
        self.reset();
95
        res
96
    }
97
98
    /// Verify the [`UniversalHash`] of the processed input matches a given [`Output`].
99
    /// This is useful when constructing Message Authentication Codes (MACs)
100
    /// from universal hash functions.
101
    fn verify(self, other: &Block<Self>) -> Result<(), Error> {
102
        if self.finalize() == other.into() {
103
            Ok(())
104
        } else {
105
            Err(Error)
106
        }
107
    }
108
}
109
110
/// Outputs of universal hash functions which are a thin wrapper around a
111
/// byte array. Provides a safe [`Eq`] implementation that runs in constant time,
112
/// which is useful for implementing Message Authentication Codes (MACs) based
113
/// on universal hashing.
114
#[derive(Clone)]
115
pub struct Output<U: UniversalHash> {
116
    bytes: GenericArray<u8, U::BlockSize>,
117
}
118
119
impl<U> Output<U>
120
where
121
    U: UniversalHash,
122
{
123
    /// Create a new [`Output`] block.
124
452
    pub fn new(bytes: Block<U>) -> Output<U> {
125
452
        Output { bytes }
126
452
    }
<universal_hash::Output<ghash::GHash>>::new
Line
Count
Source
124
226
    pub fn new(bytes: Block<U>) -> Output<U> {
125
226
        Output { bytes }
126
226
    }
<universal_hash::Output<polyval::backend::autodetect::Polyval>>::new
Line
Count
Source
124
226
    pub fn new(bytes: Block<U>) -> Output<U> {
125
226
        Output { bytes }
126
226
    }
Unexecuted instantiation: <universal_hash::Output<polyval::backend::soft::Polyval>>::new
127
128
    /// Get the inner [`GenericArray`] this type wraps
129
678
    pub fn into_bytes(self) -> Block<U> {
130
678
        self.bytes
131
678
    }
<universal_hash::Output<ghash::GHash>>::into_bytes
Line
Count
Source
129
226
    pub fn into_bytes(self) -> Block<U> {
130
226
        self.bytes
131
226
    }
<universal_hash::Output<polyval::backend::autodetect::Polyval>>::into_bytes
Line
Count
Source
129
226
    pub fn into_bytes(self) -> Block<U> {
130
226
        self.bytes
131
226
    }
Unexecuted instantiation: <universal_hash::Output<polyval::backend::soft::Polyval>>::into_bytes
<universal_hash::Output<polyval::backend::clmul::Polyval>>::into_bytes
Line
Count
Source
129
226
    pub fn into_bytes(self) -> Block<U> {
130
226
        self.bytes
131
226
    }
132
}
133
134
impl<U> From<Block<U>> for Output<U>
135
where
136
    U: UniversalHash,
137
{
138
    fn from(bytes: Block<U>) -> Self {
139
        Output { bytes }
140
    }
141
}
142
143
impl<'a, U> From<&'a Block<U>> for Output<U>
144
where
145
    U: UniversalHash,
146
{
147
    fn from(bytes: &'a Block<U>) -> Self {
148
        bytes.clone().into()
149
    }
150
}
151
152
impl<U> ConstantTimeEq for Output<U>
153
where
154
    U: UniversalHash,
155
{
156
    fn ct_eq(&self, other: &Self) -> Choice {
157
        self.bytes.ct_eq(&other.bytes)
158
    }
159
}
160
161
impl<U> PartialEq for Output<U>
162
where
163
    U: UniversalHash,
164
{
165
    fn eq(&self, x: &Output<U>) -> bool {
166
        self.ct_eq(x).unwrap_u8() == 1
167
    }
168
}
169
170
impl<U: UniversalHash> Eq for Output<U> {}
171
172
/// Error type for when the [`Output`] of a [`UniversalHash`]
173
/// is not equal to the expected value.
174
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
175
pub struct Error;
176
177
impl core::fmt::Display for Error {
178
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
179
        f.write_str("UHF output mismatch")
180
    }
181
}
182
183
#[cfg(feature = "std")]
184
impl std::error::Error for Error {}