use std::collections::HashMap;
use aes::Aes128;
use aes::cipher::{
BlockDecryptMut, KeyIvInit, block_padding::Pkcs7,
generic_array::GenericArray,
};
use base64::{
Engine, engine::general_purpose::URL_SAFE_NO_PAD as BASE64_URL_SAFE_NO_PAD,
};
use cbc::Decryptor;
use super::key_normalizer::KeyNormalizer;
use crate::{CRYPTO_LOGGER_DOMAIN, Error, debug_log, error_log};
type Aes128CbcDecryptor = Decryptor<Aes128>;
pub struct AesDecrypt;
impl AesDecrypt {
pub fn decrypt(
encrypted: &str,
key: &str,
iv: &str,
) -> Result<HashMap<String, String>, Error> {
debug_log!(
CRYPTO_LOGGER_DOMAIN,
"Starting AES decryption for Base64 string"
);
let decoded = BASE64_URL_SAFE_NO_PAD
.decode(encrypted)
.map_err(Error::Base64DecodeError)?;
let decrypted = Self::decrypt_bytes(&decoded, key, iv)?;
let dict: HashMap<String, String> =
rmp_serde::from_slice(&decrypted)
.map_err(|e| Error::DecryptionError(e.to_string()))?;
debug_log!(
CRYPTO_LOGGER_DOMAIN,
"Decryption successful, restored MessagePack dictionary"
);
Ok(dict)
}
fn decrypt_bytes(
ciphertext: &[u8],
key: &str,
iv: &str,
) -> Result<Vec<u8>, Error> {
let key = KeyNormalizer::normalize_from_str(key)?;
let iv_bytes = KeyNormalizer::normalize_from_str(iv)?;
let iv = GenericArray::from_slice(&iv_bytes);
let cipher =
Aes128CbcDecryptor::new(GenericArray::from_slice(&key), iv);
let mut buffer = ciphertext.to_vec();
let decrypted = cipher
.decrypt_padded_mut::<Pkcs7>(&mut buffer)
.map_err(|e| {
error_log!(CRYPTO_LOGGER_DOMAIN, "Decryption failed: {}", e);
Error::DecryptionError(e.to_string())
})?;
Ok(decrypted.to_vec())
}
}