dryoc/classic/
crypto_auth_hmacsha512256.rs1use subtle::ConstantTimeEq;
45use zeroize::Zeroize;
46
47use crate::classic::crypto_auth_hmac_impl::hmac_keygen;
48use crate::classic::crypto_auth_hmacsha512::{
49 HmacSha512State, crypto_auth_hmacsha512_final, crypto_auth_hmacsha512_init,
50 crypto_auth_hmacsha512_update,
51};
52use crate::constants::{
53 CRYPTO_AUTH_HMACSHA512_BYTES, CRYPTO_AUTH_HMACSHA512256_BYTES,
54 CRYPTO_AUTH_HMACSHA512256_KEYBYTES,
55};
56use crate::error::Error;
57
58pub type Key = [u8; CRYPTO_AUTH_HMACSHA512256_KEYBYTES];
60pub type Mac = [u8; CRYPTO_AUTH_HMACSHA512256_BYTES];
62pub type HmacSha512256State = HmacSha512State;
64
65pub fn crypto_auth_hmacsha512256(mac: &mut Mac, message: &[u8], key: &Key) {
67 let mut state = crypto_auth_hmacsha512256_init(key);
68 crypto_auth_hmacsha512256_update(&mut state, message);
69 crypto_auth_hmacsha512256_final(state, mac);
70}
71
72pub fn crypto_auth_hmacsha512256_verify(mac: &Mac, input: &[u8], key: &Key) -> Result<(), Error> {
78 let mut computed_mac = Mac::default();
79 crypto_auth_hmacsha512256(&mut computed_mac, input, key);
80 let valid = mac.ct_eq(&computed_mac).unwrap_u8();
81 computed_mac.zeroize();
82 if valid == 1 {
83 Ok(())
84 } else {
85 Err(Error::AuthenticationFailed)
86 }
87}
88
89pub fn crypto_auth_hmacsha512256_keygen() -> Key {
91 hmac_keygen()
92}
93
94pub fn crypto_auth_hmacsha512256_init(key: &[u8]) -> HmacSha512256State {
96 crypto_auth_hmacsha512_init(key)
97}
98
99pub fn crypto_auth_hmacsha512256_update(state: &mut HmacSha512256State, input: &[u8]) {
101 crypto_auth_hmacsha512_update(state, input);
102}
103
104pub fn crypto_auth_hmacsha512256_final(state: HmacSha512256State, output: &mut Mac) {
106 let mut full_output = [0u8; CRYPTO_AUTH_HMACSHA512_BYTES];
107 crypto_auth_hmacsha512_final(state, &mut full_output);
108 output.copy_from_slice(&full_output[..CRYPTO_AUTH_HMACSHA512256_BYTES]);
109 full_output.zeroize();
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 fn compute_hmac(key: &[u8], message: &[u8]) -> Mac {
117 let mut mac = Mac::default();
118 let mut state = crypto_auth_hmacsha512256_init(key);
119 crypto_auth_hmacsha512256_update(&mut state, message);
120 crypto_auth_hmacsha512256_final(state, &mut mac);
121 mac
122 }
123
124 fn assert_hmac(key: &[u8], message: &[u8], expected_hex: &str) {
125 let mac = compute_hmac(key, message);
126 let expected = hex::decode(expected_hex).expect("hex failed");
127 assert_eq!(mac.as_slice(), expected.as_slice());
128 }
129
130 #[test]
131 fn test_rfc4231_case_1_truncated() {
132 let key = [0x0bu8; 20];
133 assert_hmac(
134 &key,
135 b"Hi There",
136 "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde",
137 );
138 }
139
140 #[test]
141 fn test_rfc4231_short_key_case_2_truncated() {
142 assert_hmac(
143 b"Jefe",
144 b"what do ya want for nothing?",
145 "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554",
146 );
147 }
148
149 #[test]
150 fn test_rfc4231_long_key_case_6_truncated() {
151 let key = [0xaau8; 131];
152 assert_hmac(
153 &key,
154 b"Test Using Larger Than Block-Size Key - Hash Key First",
155 "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352",
156 );
157 }
158
159 #[test]
160 fn test_rfc4231_long_key_and_message_case_7_truncated() {
161 let key = [0xaau8; 131];
162 assert_hmac(
163 &key,
164 b"This is a test using a larger than block-size key and a larger than block-size data. \
165 The key needs to be hashed before being used by the HMAC algorithm.",
166 "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944",
167 );
168 }
169
170 #[test]
171 fn test_one_shot_matches_incremental_for_keybytes_key() {
172 let key = [0x0bu8; CRYPTO_AUTH_HMACSHA512256_KEYBYTES];
173 let message = b"message";
174 let mut one_shot = Mac::default();
175 crypto_auth_hmacsha512256(&mut one_shot, message, &key);
176 assert_eq!(one_shot, compute_hmac(&key, message));
177 }
178
179 #[cfg(dryoc_native_tests)]
180 #[test]
181 fn test_libsodium_compatibility() {
182 use sodiumoxide::crypto::auth::hmacsha512256;
183
184 let key = crypto_auth_hmacsha512256_keygen();
185 let message = b"message to authenticate";
186 let so_key = hmacsha512256::Key::from_slice(&key).expect("key failed");
187 let so_mac = hmacsha512256::authenticate(message, &so_key);
188
189 let mut mac = Mac::default();
190 crypto_auth_hmacsha512256(&mut mac, message, &key);
191 assert_eq!(mac.as_slice(), so_mac.as_ref());
192 crypto_auth_hmacsha512256_verify(&mac, message, &key).expect("verify failed");
193
194 let mut state = crypto_auth_hmacsha512256_init(&key);
195 crypto_auth_hmacsha512256_update(&mut state, b"message ");
196 crypto_auth_hmacsha512256_update(&mut state, b"to authenticate");
197 let mut state_mac = Mac::default();
198 crypto_auth_hmacsha512256_final(state, &mut state_mac);
199 assert_eq!(state_mac.as_slice(), so_mac.as_ref());
200 }
201}