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