Skip to main content

sentc_crypto_std_keys/core/hmac/
hmac_sha256.rs

1use alloc::vec::Vec;
2
3use hmac::{Hmac, Mac};
4use sentc_crypto_core::cryptomat::{SearchableKey, SearchableKeyGen, SymKey};
5use sentc_crypto_core::{as_ref_bytes_single_value, crypto_alg_str_impl, try_from_bytes_owned_single_value, Error};
6use sha2::Sha256;
7
8use crate::core::hmac::HmacKey;
9use crate::core::sym;
10use crate::core::sym::aes_gcm::AesKey;
11
12pub const HMAC_SHA256_OUTPUT: &str = "HMAC-SHA256";
13
14type HmacSha256 = Hmac<Sha256>;
15
16pub struct HmacSha256Key(AesKey);
17
18try_from_bytes_owned_single_value!(HmacSha256Key);
19as_ref_bytes_single_value!(HmacSha256Key);
20crypto_alg_str_impl!(HmacSha256Key, HMAC_SHA256_OUTPUT);
21
22impl Into<HmacKey> for HmacSha256Key
23{
24	fn into(self) -> HmacKey
25	{
26		HmacKey::HmacSha256(self)
27	}
28}
29
30impl SearchableKey for HmacSha256Key
31{
32	fn encrypt_key_with_master_key<M: SymKey>(&self, master_key: &M) -> Result<Vec<u8>, Error>
33	{
34		master_key.encrypt(&self.0)
35	}
36
37	fn encrypt_searchable(&self, data: &[u8]) -> Result<Vec<u8>, Error>
38	{
39		let mut mac = HmacSha256::new_from_slice(&self.0).map_err(|_| Error::HmacAuthFailedLength)?;
40
41		mac.update(data);
42
43		let result = mac.finalize();
44		let result = result.into_bytes();
45
46		Ok(result.to_vec())
47	}
48
49	fn verify_encrypted_searchable(&self, data: &[u8], check: &[u8]) -> Result<bool, Error>
50	{
51		let mut mac = HmacSha256::new_from_slice(&self.0).map_err(|_| Error::HmacAuthFailedLength)?;
52
53		mac.update(data);
54
55		Ok(mac.verify_slice(check).is_ok())
56	}
57}
58
59impl SearchableKeyGen for HmacSha256Key
60{
61	type SearchableKey = Self;
62
63	fn generate() -> Result<Self::SearchableKey, Error>
64	{
65		Ok(Self(sym::aes_gcm::raw_generate()?))
66	}
67}
68
69#[cfg(test)]
70mod test
71{
72	use super::*;
73
74	#[test]
75	fn test_create_hmac_key()
76	{
77		let _ = HmacSha256Key::generate().unwrap();
78	}
79
80	#[test]
81	fn test_plain_auth_msg()
82	{
83		let msg = "Hello world üöäéèßê°";
84
85		let out = HmacSha256Key::generate().unwrap();
86
87		let mac = out.encrypt_searchable(msg.as_bytes()).unwrap();
88
89		let verify = out
90			.verify_encrypted_searchable(msg.as_bytes(), &mac)
91			.unwrap();
92
93		assert!(verify);
94	}
95
96	#[test]
97	fn test_not_verify_with_wrong_key()
98	{
99		let msg = "Hello world üöäéèßê°";
100
101		let out = HmacSha256Key::generate().unwrap();
102		let out2 = HmacSha256Key::generate().unwrap();
103
104		let mac = out.encrypt_searchable(msg.as_bytes()).unwrap();
105
106		let verify = out2
107			.verify_encrypted_searchable(msg.as_bytes(), &mac)
108			.unwrap();
109
110		assert!(!verify);
111	}
112
113	#[test]
114	fn test_not_producing_the_same_output_with_different_keys()
115	{
116		let msg = "Hello world üöäéèßê°";
117
118		let out = HmacSha256Key::generate().unwrap();
119		let out2 = HmacSha256Key::generate().unwrap();
120
121		let mac1 = out.encrypt_searchable(msg.as_bytes()).unwrap();
122
123		let mac2 = out2.encrypt_searchable(msg.as_bytes()).unwrap();
124
125		assert_ne!(mac1, mac2);
126	}
127
128	#[test]
129	fn test_producing_the_same_output_with_same_keys()
130	{
131		let msg = "Hello world üöäéèßê°";
132
133		let out = HmacSha256Key::generate().unwrap();
134
135		let mac1 = out.encrypt_searchable(msg.as_bytes()).unwrap();
136
137		let mac2 = out.encrypt_searchable(msg.as_bytes()).unwrap();
138
139		assert_eq!(mac1, mac2);
140	}
141}