1use 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
50pub type Key = [u8; CRYPTO_AUTH_HMACSHA512_KEYBYTES];
52pub type Mac = [u8; CRYPTO_AUTH_HMACSHA512_BYTES];
54
55pub struct HmacSha512State(HmacState<Sha512, 128, CRYPTO_AUTH_HMACSHA512_BYTES>);
57
58pub 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
65pub 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
76pub fn crypto_auth_hmacsha512_keygen() -> Key {
78 hmac_keygen()
79}
80
81pub fn crypto_auth_hmacsha512_init(key: &[u8]) -> HmacSha512State {
83 HmacSha512State(hmac_init::<Sha512, 128, CRYPTO_AUTH_HMACSHA512_BYTES>(key))
84}
85
86pub fn crypto_auth_hmacsha512_update(state: &mut HmacSha512State, input: &[u8]) {
88 hmac_update(&mut state.0, input);
89}
90
91pub fn crypto_auth_hmacsha512_final(state: HmacSha512State, output: &mut Mac) {
93 hmac_final(state.0, output);
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 fn compute_hmac(key: &[u8], message: &[u8]) -> Mac {
101 let mut mac = [0u8; CRYPTO_AUTH_HMACSHA512_BYTES];
102 let mut state = crypto_auth_hmacsha512_init(key);
103 crypto_auth_hmacsha512_update(&mut state, message);
104 crypto_auth_hmacsha512_final(state, &mut mac);
105 mac
106 }
107
108 fn assert_hmac(key: &[u8], message: &[u8], expected_hex: &str) {
109 let mac = compute_hmac(key, message);
110 let expected = hex::decode(expected_hex).expect("hex failed");
111 assert_eq!(mac.as_slice(), expected.as_slice());
112 }
113
114 #[test]
115 fn test_rfc4231_case_1() {
116 let key = [0x0bu8; 20];
117 assert_hmac(
118 &key,
119 b"Hi There",
120 concat!(
121 "87aa7cdea5ef619d4ff0b4241a1d6cb0",
122 "2379f4e2ce4ec2787ad0b30545e17cde",
123 "daa833b7d6b8a702038b274eaea3f4e4",
124 "be9d914eeb61f1702e696c203a126854",
125 ),
126 );
127 }
128
129 #[test]
130 fn test_rfc4231_short_key_case_2() {
131 assert_hmac(
132 b"Jefe",
133 b"what do ya want for nothing?",
134 concat!(
135 "164b7a7bfcf819e2e395fbe73b56e0a3",
136 "87bd64222e831fd610270cd7ea250554",
137 "9758bf75c05a994a6d034f65f8f0e6fd",
138 "caeab1a34d4a6b4b636e070a38bce737",
139 ),
140 );
141 }
142
143 #[test]
144 fn test_rfc4231_long_message_case_3() {
145 let key = [0xaau8; 20];
146 let message = [0xddu8; 50];
147 assert_hmac(
148 &key,
149 &message,
150 concat!(
151 "fa73b0089d56a284efb0f0756c890be9",
152 "b1b5dbdd8ee81a3655f83e33b2279d39",
153 "bf3e848279a722c806b485a47e67c807",
154 "b946a337bee8942674278859e13292fb",
155 ),
156 );
157 }
158
159 #[test]
160 fn test_rfc4231_long_key_case_6() {
161 let key = [0xaau8; 131];
162 assert_hmac(
163 &key,
164 b"Test Using Larger Than Block-Size Key - Hash Key First",
165 concat!(
166 "80b24263c7c1a3ebb71493c1dd7be8b4",
167 "9b46d1f41b4aeec1121b013783f8f352",
168 "6b56d037e05f2598bd0fd2215d6a1e52",
169 "95e64f73f63f0aec8b915a985d786598",
170 ),
171 );
172 }
173
174 #[test]
175 fn test_rfc4231_long_key_and_message_case_7() {
176 let key = [0xaau8; 131];
177 assert_hmac(
178 &key,
179 b"This is a test using a larger than block-size key and a larger than block-size data. \
180 The key needs to be hashed before being used by the HMAC algorithm.",
181 concat!(
182 "e37b6a775dc87dbaa4dfa9f96e5e3ffd",
183 "debd71f8867289865df5a32d20cdc944",
184 "b6022cac3c4982b10d5eeb55c3e4de15",
185 "134676fb6de0446065c97440fa8c6a58",
186 ),
187 );
188 }
189
190 #[test]
191 fn test_rfc4231_case_4() {
192 let key =
193 hex::decode("0102030405060708090a0b0c0d0e0f10111213141516171819").expect("hex failed");
194 let message = [0xcdu8; 50];
195 assert_hmac(
196 &key,
197 &message,
198 concat!(
199 "b0ba465637458c6990e5a8c5f61d4af7",
200 "e576d97ff94b872de76f8050361ee3db",
201 "a91ca5c11aa25eb4d679275cc5788063",
202 "a5f19741120c4f2de2adebeb10a298dd",
203 ),
204 );
205 }
206
207 #[test]
208 fn test_rfc4231_case_1_matches_one_shot_for_keybytes_key() {
209 let key = [0x0bu8; CRYPTO_AUTH_HMACSHA512_KEYBYTES];
210 let message = b"Hi There";
211 let mut one_shot = [0u8; CRYPTO_AUTH_HMACSHA512_BYTES];
212 crypto_auth_hmacsha512(&mut one_shot, message, &key);
213 assert_eq!(one_shot, compute_hmac(&key, message));
214 }
215
216 #[cfg(dryoc_native_tests)]
217 #[test]
218 fn test_libsodium_compatibility() {
219 use sodiumoxide::crypto::auth::hmacsha512;
220
221 let key = crypto_auth_hmacsha512_keygen();
222 let message = b"message to authenticate";
223 let so_key = hmacsha512::Key::from_slice(&key).expect("key failed");
224 let so_mac = hmacsha512::authenticate(message, &so_key);
225
226 let mut mac = [0u8; CRYPTO_AUTH_HMACSHA512_BYTES];
227 crypto_auth_hmacsha512(&mut mac, message, &key);
228 assert_eq!(mac.as_slice(), so_mac.as_ref());
229 crypto_auth_hmacsha512_verify(&mac, message, &key).expect("verify failed");
230
231 let mut state = crypto_auth_hmacsha512_init(&key);
232 crypto_auth_hmacsha512_update(&mut state, b"message ");
233 crypto_auth_hmacsha512_update(&mut state, b"to authenticate");
234 let mut state_mac = [0u8; CRYPTO_AUTH_HMACSHA512_BYTES];
235 crypto_auth_hmacsha512_final(state, &mut state_mac);
236 assert_eq!(state_mac.as_slice(), so_mac.as_ref());
237 }
238}