mod blake2;
mod blake3;
mod block;
mod hmac;
mod k12;
mod keccak;
mod kmac;
mod md4;
mod md5;
mod ripemd160;
mod sha1;
mod sha256;
mod sha3;
mod sha512;
#[cfg(all(feature = "std", any(target_arch = "x86_64", target_arch = "aarch64")))]
mod sha_hw;
mod shake;
mod sm3;
mod zeroize;
pub use blake2::{
Blake2b256, Blake2b384, Blake2b512, Blake2bMac, Blake2s256, Blake2sMac, Blake2xb,
Blake2xbReader, Blake2xs, Blake2xsReader, blake2b256, blake2b384, blake2b512, blake2s256,
};
pub use blake3::{Blake3, Blake3Reader, blake3};
pub use hmac::{
Hmac, HmacSha224, HmacSha256, HmacSha384, HmacSha512, HmacSha512_224, HmacSha512_256,
};
pub use k12::{KangarooTwelve, TurboShake128, TurboShake256, k12};
pub use keccak::KeccakReader;
pub use kmac::{
CShake128, CShake256, Kmac128, Kmac256, KmacXof128, KmacXof256, ParallelHash128,
ParallelHash256, TupleHash128, TupleHash256,
};
pub use md4::{Md4, md4};
pub use md5::{Md5, md5};
pub use ripemd160::{Ripemd160, ripemd160};
pub use sha1::{Sha1, sha1};
pub use sha3::{
Keccak256, Sha3_224, Sha3_256, Sha3_384, Sha3_512, keccak256, sha3_224, sha3_256, sha3_384,
sha3_512,
};
pub use sha256::{Sha224, Sha256, sha224, sha256};
pub use sha512::{Sha384, Sha512, Sha512_224, Sha512_256, sha384, sha512, sha512_224, sha512_256};
pub use shake::{Shake128, Shake256, shake128, shake256};
pub use sm3::{Sm3, sm3};
pub trait Digest: Clone {
type Output: AsRef<[u8]> + AsMut<[u8]> + Copy;
type Block: AsRef<[u8]> + AsMut<[u8]> + Copy;
const OUTPUT_LEN: usize;
const BLOCK_LEN: usize;
fn new() -> Self;
fn zeroed_block() -> Self::Block;
fn zeroed_output() -> Self::Output;
fn update(&mut self, data: &[u8]);
fn finalize(self) -> Self::Output;
#[inline]
fn digest(data: &[u8]) -> Self::Output {
let mut hasher = Self::new();
hasher.update(data);
hasher.finalize()
}
#[inline]
fn zeroize(&mut self) {}
}
pub trait ExtendableOutput: Clone {
type Reader: XofReader;
const BLOCK_LEN: usize;
fn new() -> Self;
fn update(&mut self, data: &[u8]);
fn finalize_xof(self) -> Self::Reader;
#[inline]
fn finalize_into(self, out: &mut [u8]) {
self.finalize_xof().read(out);
}
#[inline]
fn xof(data: &[u8], out: &mut [u8]) {
let mut x = Self::new();
x.update(data);
x.finalize_into(out);
}
}
pub trait XofReader {
fn read(&mut self, out: &mut [u8]);
}
pub trait Mac: Clone {
const OUTPUT_LEN: Option<usize> = None;
fn update(&mut self, data: &[u8]);
fn finalize_into(self, out: &mut [u8]);
fn verify(self, expected: &[u8]) -> crate::ct::Choice {
use crate::ct::ConstantTimeEq;
let n = match Self::OUTPUT_LEN {
Some(len) => len.min(64),
None => {
if expected.is_empty() {
return crate::ct::Choice::from(0u8);
}
expected.len().min(64)
}
};
let mut buf = [0u8; 64];
self.finalize_into(&mut buf[..n]);
let eq = buf[..n].ct_eq(expected);
zeroize::zero_bytes(&mut buf);
eq
}
}
#[cfg(test)]
mod tests {
use super::{Kmac128, Kmac256, Mac};
#[test]
fn mac_verify_rejects_empty_tag() {
let key = [0x42u8; 32];
let data = b"empty tags must never verify";
let mut m = Kmac128::new(&key, b"");
Mac::update(&mut m, data);
assert!(!bool::from(Mac::verify(m, b"")));
let mut m = Kmac256::new(&key, b"App");
Mac::update(&mut m, data);
assert!(!bool::from(Mac::verify(m, b"")));
let mut m = Kmac256::new(&key, b"App");
Mac::update(&mut m, data);
let mut tag = [0u8; 32];
Mac::finalize_into(m.clone(), &mut tag);
assert!(bool::from(Mac::verify(m, &tag)));
}
}