1use crate::credentials::Secret;
7#[cfg(any(feature = "hmac_rust", feature = "hmac_openssl"))]
8use crate::{
9 base64,
10 error::{ErrorKind, ResultExt},
11};
12
13#[cfg(all(feature = "hmac_rust", not(feature = "hmac_openssl")))]
25pub fn hmac_sha256(data: &str, key: &Secret) -> crate::Result<String> {
26 use hmac::{Hmac, Mac};
27 use sha2::Sha256;
28 let key = base64::decode(key.secret())?;
29 let mut hmac = Hmac::<Sha256>::new_from_slice(&key)
30 .with_context_fn(ErrorKind::DataConversion, || {
31 "failed to create hmac from key"
32 })?;
33 hmac.update(data.as_bytes());
34 let signature = hmac.finalize().into_bytes();
35 Ok(base64::encode(signature))
36}
37
38#[cfg(feature = "hmac_openssl")]
50pub fn hmac_sha256(data: &str, key: &Secret) -> crate::Result<String> {
51 use openssl::{error::ErrorStack, hash::MessageDigest, pkey::PKey, sign::Signer};
53
54 let decoded = base64::decode(key.secret())?;
55 let signature = || -> Result<Vec<u8>, ErrorStack> {
56 let pkey = PKey::hmac(&decoded)?;
57 let mut signer = Signer::new(MessageDigest::sha256(), &pkey)?;
58 signer.update(data.as_bytes())?;
59 signer.sign_to_vec()
60 }()
61 .with_context_fn(ErrorKind::DataConversion, || {
62 "failed to create hmac from key"
63 })?;
64 Ok(base64::encode(signature))
65}
66
67#[cfg(not(any(feature = "hmac_rust", feature = "hmac_openssl")))]
73pub fn hmac_sha256(_data: &str, _key: &Secret) -> crate::Result<String> {
74 unimplemented!("An HMAC signing request was called without an hmac implementation. Make sure to enable either the `hmac_rust` or `hmac_openssl` feature");
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[allow(dead_code)]
82 #[cfg_attr(any(feature = "hmac_rust", feature = "hmac_openssl"), test)]
83 fn test_hmac_sign() {
84 let data = "create hmac signature for data";
85 let key = Secret::new("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
86
87 let sig = hmac_sha256(data, &key).unwrap();
88
89 let expected_sig = "D/y9XyIEdUzEbdV570h8dou/mfkbMA1lKCOPqPDPAd0=";
90 assert_eq!(sig, expected_sig);
91 }
92}