Skip to main content

dryoc/classic/
crypto_auth_hmacsha512256.rs

1//! # HMAC-SHA-512-256 authentication
2//!
3//! Implements libsodium's `crypto_auth_hmacsha512256_*` functions.
4//!
5//! HMAC-SHA-512-256 is HMAC-SHA-512 with a 32-byte truncated output. This is
6//! libsodium's default `crypto_auth` construction. It authenticates a public
7//! message with a shared secret key; it does not hide the message contents.
8//!
9//! ```
10//! use dryoc::classic::crypto_auth_hmacsha512256::*;
11//!
12//! let key = crypto_auth_hmacsha512256_keygen();
13//! let message = b"No legacy is so rich as honesty.";
14//!
15//! let mut mac = Mac::default();
16//! crypto_auth_hmacsha512256(&mut mac, message, &key);
17//! crypto_auth_hmacsha512256_verify(&mac, message, &key).expect("verify failed");
18//! crypto_auth_hmacsha512256_verify(&mac, b"invalid", &key).expect_err("verify should fail");
19//! ```
20//!
21//! The incremental interface produces the same truncated HMAC-SHA-512 MAC as
22//! the one-shot interface:
23//!
24//! ```
25//! use dryoc::classic::crypto_auth_hmacsha512256::*;
26//!
27//! let key = crypto_auth_hmacsha512256_keygen();
28//! let mut one_shot = Mac::default();
29//! crypto_auth_hmacsha512256(
30//!     &mut one_shot,
31//!     b"Small cheer and great welcome makes a merry feast.",
32//!     &key,
33//! );
34//!
35//! let mut state = crypto_auth_hmacsha512256_init(&key);
36//! crypto_auth_hmacsha512256_update(&mut state, b"Small cheer and great welcome ");
37//! crypto_auth_hmacsha512256_update(&mut state, b"makes a merry feast.");
38//! let mut streaming = Mac::default();
39//! crypto_auth_hmacsha512256_final(state, &mut streaming);
40//!
41//! assert_eq!(one_shot, streaming);
42//! ```
43
44use crate::classic::crypto_auth_hmac_impl::hmac_keygen;
45use crate::classic::crypto_auth_hmacsha512::{
46    HmacSha512State, crypto_auth_hmacsha512_final, crypto_auth_hmacsha512_init,
47    crypto_auth_hmacsha512_update,
48};
49use crate::constants::{
50    CRYPTO_AUTH_HMACSHA512_BYTES, CRYPTO_AUTH_HMACSHA512256_BYTES,
51    CRYPTO_AUTH_HMACSHA512256_KEYBYTES,
52};
53use crate::error::Error;
54use crate::utils::{verify_ct, zeroize_bytes};
55
56/// Key for HMAC-SHA-512-256 message authentication.
57pub type Key = [u8; CRYPTO_AUTH_HMACSHA512256_KEYBYTES];
58/// Message authentication code type for HMAC-SHA-512-256.
59pub type Mac = [u8; CRYPTO_AUTH_HMACSHA512256_BYTES];
60/// Internal state for HMAC-SHA-512-256.
61pub type HmacSha512256State = HmacSha512State;
62
63/// Authenticates `message` using `key`, and places the result into `mac`.
64pub fn crypto_auth_hmacsha512256(mac: &mut Mac, message: &[u8], key: &Key) {
65    let mut state = crypto_auth_hmacsha512256_init(key);
66    crypto_auth_hmacsha512256_update(&mut state, message);
67    crypto_auth_hmacsha512256_final(state, mac);
68}
69
70/// Verifies that `mac` is the correct authenticator for `message` using `key`.
71///
72/// # Errors
73///
74/// Returns an error if `mac` is not valid for `input` under `key`.
75pub fn crypto_auth_hmacsha512256_verify(mac: &Mac, input: &[u8], key: &Key) -> Result<(), Error> {
76    let mut computed_mac = Mac::default();
77    crypto_auth_hmacsha512256(&mut computed_mac, input, key);
78    let result = verify_ct(mac, &computed_mac);
79    zeroize_bytes(&mut computed_mac);
80    result
81}
82
83/// Generates a random key for HMAC-SHA-512-256.
84#[must_use]
85pub fn crypto_auth_hmacsha512256_keygen() -> Key {
86    hmac_keygen()
87}
88
89/// Initializes the incremental interface for HMAC-SHA-512-256.
90#[must_use]
91pub fn crypto_auth_hmacsha512256_init(key: &[u8]) -> HmacSha512256State {
92    crypto_auth_hmacsha512_init(key)
93}
94
95/// Updates `state` for HMAC-SHA-512-256 with `input`.
96pub fn crypto_auth_hmacsha512256_update(state: &mut HmacSha512256State, input: &[u8]) {
97    crypto_auth_hmacsha512_update(state, input);
98}
99
100/// Finalizes HMAC-SHA-512-256 and places the truncated result into `output`.
101pub fn crypto_auth_hmacsha512256_final(state: HmacSha512256State, output: &mut Mac) {
102    let mut full_output = [0u8; CRYPTO_AUTH_HMACSHA512_BYTES];
103    crypto_auth_hmacsha512_final(state, &mut full_output);
104    output.copy_from_slice(&full_output[..CRYPTO_AUTH_HMACSHA512256_BYTES]);
105    zeroize_bytes(&mut full_output);
106}
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111    use crate::classic::crypto_auth_hmac_impl::test_util::hmac_classic_tests;
112
113    hmac_classic_tests! {
114        hash: sha2::Sha512,
115        block: 128,
116        bytes: CRYPTO_AUTH_HMACSHA512256_BYTES,
117        keybytes: CRYPTO_AUTH_HMACSHA512256_KEYBYTES,
118        tag: sha512256,
119        chunk: 31,
120        one_shot: crypto_auth_hmacsha512256,
121        verify: crypto_auth_hmacsha512256_verify,
122        keygen: crypto_auth_hmacsha512256_keygen,
123        init: crypto_auth_hmacsha512256_init,
124        update: crypto_auth_hmacsha512256_update,
125        finalize: crypto_auth_hmacsha512256_final,
126        sodium_one_shot: auth_hmacsha512256,
127        sodium_state: AuthHmacSha512256State,
128        keybytes_test: test_one_shot_matches_incremental_for_keybytes_key(b"message"),
129        rfc4231: {
130            test_rfc4231_case_1_truncated => RFC4231_CASE_1,
131            test_rfc4231_short_key_case_2_truncated => RFC4231_CASE_2,
132            test_rfc4231_long_key_case_6_truncated => RFC4231_CASE_6,
133            test_rfc4231_long_key_and_message_case_7_truncated => RFC4231_CASE_7,
134        },
135    }
136}