diff --git a/blake2/README.md b/blake2/README.md index 91a92212e..29c294bfb 100644 --- a/blake2/README.md +++ b/blake2/README.md @@ -73,6 +73,22 @@ let res = hasher.finalize(); assert_eq!(res, hex!("2cc55c84e416924e6400")); ``` +### Message Authentication Code (MAC) + +BLAKE2 can be used as a MAC with variable output size set at compile time: + +```rust +use blake2::Blake2bMac; +use blake2::digest::{Update, FixedOutput, consts::U16}; +use hex_literal::hex; + +let mut hasher: Blake2bMac<U16> = Blake2bMac::new_with_key(b"my_key").unwrap(); +hasher.update(b"my_input"); +let res = hasher.finalize_fixed(); + +assert_eq!(res.as_ref(), hex!("3c3869ce1c58d0569827a731d8eab099")); +``` + ## Minimum Supported Rust Version Rust **1.71** or higher. diff --git a/blake2/src/macros.rs b/blake2/src/macros.rs index b17adb987..9b1bf61e6 100644 --- a/blake2/src/macros.rs +++ b/blake2/src/macros.rs @@ -284,7 +284,7 @@ macro_rules! blake2_mac_impl { OutSize: ArraySize + IsLessOrEqual<$max_size>, LeEq<OutSize, $max_size>: NonZero, { - /// Create new instance using provided key, salt, and persona. + /// Create new instance using the provided key, salt, and persona. /// /// # Errors /// @@ -318,6 +318,14 @@ macro_rules! blake2_mac_impl { _out: PhantomData, }) } + /// Creates a new instance using the provided key, skipping the salt + /// and persona. This method is equivalent to calling + /// [`new_with_salt_and_personal`](Self::new_with_salt_and_personal) + /// with empty slices for the salt and persona. + #[inline] + pub fn new_with_key(key: &[u8]) -> Result<Self, InvalidLength> { + Self::new_with_salt_and_personal(key, &[], &[]) + } } impl<OutSize> KeySizeUser for $name<OutSize> diff --git a/blake2/tests/mac.rs b/blake2/tests/mac.rs index 7a166a047..4a83ae700 100644 --- a/blake2/tests/mac.rs +++ b/blake2/tests/mac.rs @@ -33,3 +33,14 @@ fn mac_refuses_empty_keys() { assert!(blake2::Blake2bMac512::new_with_salt_and_personal(&[], b"salt", b"persona").is_err()); assert!(blake2::Blake2sMac256::new_with_salt_and_personal(&[], b"salt", b"persona").is_err()); } + +#[test] +fn blake2b_with_key_equivalence() { + use blake2::digest::FixedOutput; + + let key = b"my_key"; + // Those two calls are equivalent. + let ctx1 = blake2::Blake2bMac512::new_with_salt_and_personal(key, &[], &[]).unwrap(); + let ctx2 = blake2::Blake2bMac512::new_with_key(key).unwrap(); + assert_eq!(ctx1.finalize_fixed(), ctx2.finalize_fixed(),); +}