Skip to main content

dryoc/classic/
crypto_auth_hmacsha512.rs

1//! # HMAC-SHA-512 authentication
2//!
3//! Implements libsodium's `crypto_auth_hmacsha512_*` functions.
4//!
5//! HMAC-SHA-512 authenticates a message with a shared secret key and writes a
6//! 64-byte tag. Use it when a protocol specifically requires HMAC-SHA-512.
7//! Verification fails if either the message or the tag has been changed.
8//!
9//! ```
10//! use dryoc::classic::crypto_auth_hmacsha512::*;
11//!
12//! let key = crypto_auth_hmacsha512_keygen();
13//! let message = b"One touch of nature makes the whole world kin.";
14//!
15//! let mut mac: Mac = [0u8; 64];
16//! crypto_auth_hmacsha512(&mut mac, message, &key);
17//! crypto_auth_hmacsha512_verify(&mac, message, &key).expect("verify failed");
18//! crypto_auth_hmacsha512_verify(&mac, b"invalid", &key).expect_err("verify should fail");
19//! ```
20//!
21//! The incremental interface produces the same MAC as the one-shot interface:
22//!
23//! ```
24//! use dryoc::classic::crypto_auth_hmacsha512::*;
25//!
26//! let key = crypto_auth_hmacsha512_keygen();
27//! let mut one_shot: Mac = [0u8; 64];
28//! crypto_auth_hmacsha512(
29//!     &mut one_shot,
30//!     b"How far that little candle throws his beams!",
31//!     &key,
32//! );
33//!
34//! let mut state = crypto_auth_hmacsha512_init(&key);
35//! crypto_auth_hmacsha512_update(&mut state, b"How far that little candle ");
36//! crypto_auth_hmacsha512_update(&mut state, b"throws his beams!");
37//! let mut streaming: Mac = [0u8; 64];
38//! crypto_auth_hmacsha512_final(state, &mut streaming);
39//!
40//! assert_eq!(one_shot, streaming);
41//! ```
42
43use crate::classic::crypto_auth_hmac_impl::{
44    HmacState, hmac, hmac_final, hmac_init, hmac_keygen, hmac_update, hmac_verify,
45};
46use crate::constants::{CRYPTO_AUTH_HMACSHA512_BYTES, CRYPTO_AUTH_HMACSHA512_KEYBYTES};
47use crate::error::Error;
48use crate::sha512::Sha512;
49
50/// Key for HMAC-SHA-512 message authentication.
51pub type Key = [u8; CRYPTO_AUTH_HMACSHA512_KEYBYTES];
52/// Message authentication code type for HMAC-SHA-512.
53pub type Mac = [u8; CRYPTO_AUTH_HMACSHA512_BYTES];
54
55/// Internal state for HMAC-SHA-512.
56pub struct HmacSha512State(HmacState<Sha512, 128, CRYPTO_AUTH_HMACSHA512_BYTES>);
57
58/// Authenticates `message` using `key`, and places the result into `mac`.
59pub fn crypto_auth_hmacsha512(mac: &mut Mac, message: &[u8], key: &Key) {
60    hmac::<Sha512, CRYPTO_AUTH_HMACSHA512_KEYBYTES, 128, CRYPTO_AUTH_HMACSHA512_BYTES>(
61        mac, message, key,
62    );
63}
64
65/// Verifies that `mac` is the correct authenticator for `message` using `key`.
66///
67/// # Errors
68///
69/// Returns an error if `mac` is not valid for `input` under `key`.
70pub fn crypto_auth_hmacsha512_verify(mac: &Mac, input: &[u8], key: &Key) -> Result<(), Error> {
71    hmac_verify::<Sha512, CRYPTO_AUTH_HMACSHA512_KEYBYTES, 128, CRYPTO_AUTH_HMACSHA512_BYTES>(
72        mac, input, key,
73    )
74}
75
76/// Generates a random key for HMAC-SHA-512.
77#[must_use]
78pub fn crypto_auth_hmacsha512_keygen() -> Key {
79    hmac_keygen()
80}
81
82/// Initializes the incremental interface for HMAC-SHA-512.
83#[must_use]
84pub fn crypto_auth_hmacsha512_init(key: &[u8]) -> HmacSha512State {
85    HmacSha512State(hmac_init::<Sha512, 128, CRYPTO_AUTH_HMACSHA512_BYTES>(key))
86}
87
88/// Updates `state` for HMAC-SHA-512 with `input`.
89pub fn crypto_auth_hmacsha512_update(state: &mut HmacSha512State, input: &[u8]) {
90    hmac_update(&mut state.0, input);
91}
92
93/// Finalizes HMAC-SHA-512 and places the result into `output`.
94pub fn crypto_auth_hmacsha512_final(state: HmacSha512State, output: &mut Mac) {
95    hmac_final(state.0, output);
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101    use crate::classic::crypto_auth_hmac_impl::test_util::hmac_classic_tests;
102
103    hmac_classic_tests! {
104        hash: sha2::Sha512,
105        block: 128,
106        bytes: CRYPTO_AUTH_HMACSHA512_BYTES,
107        keybytes: CRYPTO_AUTH_HMACSHA512_KEYBYTES,
108        tag: sha512,
109        chunk: 31,
110        one_shot: crypto_auth_hmacsha512,
111        verify: crypto_auth_hmacsha512_verify,
112        keygen: crypto_auth_hmacsha512_keygen,
113        init: crypto_auth_hmacsha512_init,
114        update: crypto_auth_hmacsha512_update,
115        finalize: crypto_auth_hmacsha512_final,
116        sodium_one_shot: auth_hmacsha512,
117        sodium_state: AuthHmacSha512State,
118        keybytes_test: test_rfc4231_case_1_matches_one_shot_for_keybytes_key(b"Hi There"),
119        rfc4231: {
120            test_rfc4231_case_1 => RFC4231_CASE_1,
121            test_rfc4231_short_key_case_2 => RFC4231_CASE_2,
122            test_rfc4231_long_message_case_3 => RFC4231_CASE_3,
123            test_rfc4231_case_4 => RFC4231_CASE_4,
124            test_rfc4231_long_key_case_6 => RFC4231_CASE_6,
125            test_rfc4231_long_key_and_message_case_7 => RFC4231_CASE_7,
126        },
127    }
128}