azure_core/
hmac.rs
1use crate::auth::Secret;
2#[cfg(any(feature = "hmac_rust", feature = "hmac_openssl"))]
3use crate::{
4 base64,
5 error::{ErrorKind, ResultExt},
6};
7
8#[cfg(all(feature = "hmac_rust", not(feature = "hmac_openssl")))]
18pub fn hmac_sha256(data: &str, key: &Secret) -> crate::Result<String> {
19 use hmac::{Hmac, Mac};
20 use sha2::Sha256;
21 let key = base64::decode(key.secret())?;
22 let mut hmac = Hmac::<Sha256>::new_from_slice(&key)
23 .with_context(ErrorKind::DataConversion, || {
24 "failed to create hmac from key"
25 })?;
26 hmac.update(data.as_bytes());
27 let signature = hmac.finalize().into_bytes();
28 Ok(base64::encode(signature))
29}
30
31#[cfg(feature = "hmac_openssl")]
32pub fn hmac_sha256(data: &str, key: &Secret) -> crate::Result<String> {
33 use openssl::{error::ErrorStack, hash::MessageDigest, pkey::PKey, sign::Signer};
34
35 let dkey = base64::decode(key.secret())?;
36 let signature = || -> Result<Vec<u8>, ErrorStack> {
37 let pkey = PKey::hmac(&dkey)?;
38 let mut signer = Signer::new(MessageDigest::sha256(), &pkey)?;
39 signer.update(data.as_bytes())?;
40 signer.sign_to_vec()
41 }()
42 .with_context(ErrorKind::DataConversion, || {
43 "failed to create hmac from key"
44 })?;
45 Ok(base64::encode(signature))
46}
47
48#[cfg(not(any(feature = "hmac_rust", feature = "hmac_openssl")))]
49pub fn hmac_sha256(_data: &str, _key: &Secret) -> crate::Result<String> {
50 unimplemented!("An HMAC signing request was called without an hmac implementation. Make sure to enable either the `hmac_rust` or `hmac_openssl` feature");
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn test_hmac_sign() {
59 let data = "create hmac signature for data";
60 let key = Secret::new("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
61
62 let sig = hmac_sha256(data, &key).unwrap();
63
64 let expected_sig = "D/y9XyIEdUzEbdV570h8dou/mfkbMA1lKCOPqPDPAd0=";
65 assert_eq!(sig, expected_sig);
66 }
67}