dryoc/classic/
crypto_auth_hmacsha256.rs1use crate::classic::crypto_auth_hmac_impl::{
41 HmacState, hmac, hmac_final, hmac_init, hmac_keygen, hmac_update, hmac_verify,
42};
43use crate::constants::{CRYPTO_AUTH_HMACSHA256_BYTES, CRYPTO_AUTH_HMACSHA256_KEYBYTES};
44use crate::error::Error;
45use crate::sha256::Sha256;
46
47pub type Key = [u8; CRYPTO_AUTH_HMACSHA256_KEYBYTES];
49pub type Mac = [u8; CRYPTO_AUTH_HMACSHA256_BYTES];
51
52pub struct HmacSha256State(HmacState<Sha256, 64, CRYPTO_AUTH_HMACSHA256_BYTES>);
54
55pub fn crypto_auth_hmacsha256(mac: &mut Mac, message: &[u8], key: &Key) {
57 hmac::<Sha256, CRYPTO_AUTH_HMACSHA256_KEYBYTES, 64, CRYPTO_AUTH_HMACSHA256_BYTES>(
58 mac, message, key,
59 );
60}
61
62pub fn crypto_auth_hmacsha256_verify(mac: &Mac, input: &[u8], key: &Key) -> Result<(), Error> {
68 hmac_verify::<Sha256, CRYPTO_AUTH_HMACSHA256_KEYBYTES, 64, CRYPTO_AUTH_HMACSHA256_BYTES>(
69 mac, input, key,
70 )
71}
72
73pub fn crypto_auth_hmacsha256_keygen() -> Key {
75 hmac_keygen()
76}
77
78pub fn crypto_auth_hmacsha256_init(key: &[u8]) -> HmacSha256State {
80 HmacSha256State(hmac_init::<Sha256, 64, CRYPTO_AUTH_HMACSHA256_BYTES>(key))
81}
82
83pub fn crypto_auth_hmacsha256_update(state: &mut HmacSha256State, input: &[u8]) {
85 hmac_update(&mut state.0, input);
86}
87
88pub fn crypto_auth_hmacsha256_final(state: HmacSha256State, output: &mut Mac) {
90 hmac_final(state.0, output);
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 fn compute_hmac(key: &[u8], message: &[u8]) -> Mac {
98 let mut mac = Mac::default();
99 let mut state = crypto_auth_hmacsha256_init(key);
100 crypto_auth_hmacsha256_update(&mut state, message);
101 crypto_auth_hmacsha256_final(state, &mut mac);
102 mac
103 }
104
105 fn assert_hmac(key: &[u8], message: &[u8], expected_hex: &str) {
106 let mac = compute_hmac(key, message);
107 let expected = hex::decode(expected_hex).expect("hex failed");
108 assert_eq!(mac.as_slice(), expected.as_slice());
109 }
110
111 #[test]
112 fn test_rfc4231_case_1() {
113 let key = [0x0bu8; 20];
114 assert_hmac(
115 &key,
116 b"Hi There",
117 "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
118 );
119 }
120
121 #[test]
122 fn test_rfc4231_short_key_case_2() {
123 assert_hmac(
124 b"Jefe",
125 b"what do ya want for nothing?",
126 "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
127 );
128 }
129
130 #[test]
131 fn test_rfc4231_long_message_case_3() {
132 let key = [0xaau8; 20];
133 let message = [0xddu8; 50];
134 assert_hmac(
135 &key,
136 &message,
137 "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
138 );
139 }
140
141 #[test]
142 fn test_rfc4231_case_4() {
143 let key =
144 hex::decode("0102030405060708090a0b0c0d0e0f10111213141516171819").expect("hex failed");
145 let message = [0xcdu8; 50];
146 assert_hmac(
147 &key,
148 &message,
149 "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
150 );
151 }
152
153 #[test]
154 fn test_rfc4231_long_key_case_6() {
155 let key = [0xaau8; 131];
156 assert_hmac(
157 &key,
158 b"Test Using Larger Than Block-Size Key - Hash Key First",
159 "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
160 );
161 }
162
163 #[test]
164 fn test_rfc4231_long_key_and_message_case_7() {
165 let key = [0xaau8; 131];
166 assert_hmac(
167 &key,
168 b"This is a test using a larger than block-size key and a larger than block-size data. \
169 The key needs to be hashed before being used by the HMAC algorithm.",
170 "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
171 );
172 }
173
174 #[test]
175 fn test_one_shot_matches_incremental_for_keybytes_key() {
176 let key = [0x0bu8; CRYPTO_AUTH_HMACSHA256_KEYBYTES];
177 let message = b"message";
178 let mut one_shot = Mac::default();
179 crypto_auth_hmacsha256(&mut one_shot, message, &key);
180 assert_eq!(one_shot, compute_hmac(&key, message));
181 }
182
183 #[cfg(dryoc_native_tests)]
184 #[test]
185 fn test_libsodium_compatibility() {
186 use sodiumoxide::crypto::auth::hmacsha256;
187
188 let key = crypto_auth_hmacsha256_keygen();
189 let message = b"message to authenticate";
190 let so_key = hmacsha256::Key::from_slice(&key).expect("key failed");
191 let so_mac = hmacsha256::authenticate(message, &so_key);
192
193 let mut mac = Mac::default();
194 crypto_auth_hmacsha256(&mut mac, message, &key);
195 assert_eq!(mac.as_slice(), so_mac.as_ref());
196 crypto_auth_hmacsha256_verify(&mac, message, &key).expect("verify failed");
197
198 let mut state = crypto_auth_hmacsha256_init(&key);
199 crypto_auth_hmacsha256_update(&mut state, b"message ");
200 crypto_auth_hmacsha256_update(&mut state, b"to authenticate");
201 let mut state_mac = Mac::default();
202 crypto_auth_hmacsha256_final(state, &mut state_mac);
203 assert_eq!(state_mac.as_slice(), so_mac.as_ref());
204 }
205}