use std::collections::HashMap;
use aes::Aes128;
use aes::cipher::{
BlockEncryptMut, KeyIvInit, block_padding::Pkcs7,
generic_array::GenericArray,
};
use base64::{Engine, engine::general_purpose::STANDARD as BASE64};
use cbc::Encryptor;
use serde_json;
use super::key_normalizer::KeyNormalizer;
use crate::{CRYPTO_LOGGER_DOMAIN, Error, debug_log, error_log};
type Aes128CbcEncryptor = Encryptor<Aes128>;
pub struct AesEncrypt;
impl AesEncrypt {
pub fn encrypt(
dict: &HashMap<String, String>,
key: &str,
iv: &str,
) -> Result<String, Error> {
debug_log!(
CRYPTO_LOGGER_DOMAIN,
"Starting AES encryption for dictionary"
);
let json = serde_json::to_string(dict).map_err(|e| {
error_log!(
CRYPTO_LOGGER_DOMAIN,
"Failed to serialize dictionary to JSON: {}",
e
);
Error::JsonError(e)
})?;
let key = KeyNormalizer::normalize_from_str(key)?;
let iv_bytes = KeyNormalizer::normalize_from_str(iv)?;
let iv = GenericArray::from_slice(&iv_bytes);
let cipher =
Aes128CbcEncryptor::new(GenericArray::from_slice(&key), iv);
let plaintext = json.as_bytes();
let mut output = vec![0u8; plaintext.len() + 16];
let ciphertext = cipher
.encrypt_padded_b2b_mut::<Pkcs7>(plaintext, &mut output)
.map_err(|e| {
error_log!(CRYPTO_LOGGER_DOMAIN, "Encryption failed: {}", e);
Error::EncryptionError(e.to_string())
})?;
let encoded = BASE64.encode(ciphertext);
debug_log!(
CRYPTO_LOGGER_DOMAIN,
"Encryption successful, produced Base64 string"
);
Ok(encoded)
}
}