use crate::crypto::{active, AesKeySize, Padding};
fn map_err(e: crate::crypto::Error) -> &'static str {
match e {
crate::crypto::Error::InvalidInput(s) => s,
crate::crypto::Error::Verification(s) => s,
crate::crypto::Error::Backend(s) => s,
crate::crypto::Error::AlgorithmNotPermitted { .. } => {
"AES algorithm rejected by active CryptoProvider's policy"
},
}
}
#[allow(dead_code)]
pub fn aes128_encrypt(key: &[u8], iv: &[u8], data: &[u8]) -> Result<Vec<u8>, &'static str> {
active()
.symmetric()
.aes_cbc_encrypt(AesKeySize::Aes128, key, iv, data, Padding::Pkcs7)
.map_err(map_err)
}
pub fn aes128_encrypt_no_padding(
key: &[u8],
iv: &[u8],
data: &[u8],
) -> Result<Vec<u8>, &'static str> {
if data.is_empty() {
return Ok(Vec::new());
}
active()
.symmetric()
.aes_cbc_encrypt(AesKeySize::Aes128, key, iv, data, Padding::None)
.map_err(map_err)
}
pub fn aes256_decrypt_no_padding(
key: &[u8],
iv: &[u8],
data: &[u8],
) -> Result<Vec<u8>, &'static str> {
if data.is_empty() {
return Ok(Vec::new());
}
active()
.symmetric()
.aes_cbc_decrypt(AesKeySize::Aes256, key, iv, data, Padding::None)
.map_err(map_err)
}
pub fn aes256_encrypt_no_padding(
key: &[u8],
iv: &[u8],
data: &[u8],
) -> Result<Vec<u8>, &'static str> {
if data.is_empty() {
return Ok(Vec::new());
}
active()
.symmetric()
.aes_cbc_encrypt(AesKeySize::Aes256, key, iv, data, Padding::None)
.map_err(map_err)
}
pub fn aes128_decrypt(key: &[u8], iv: &[u8], data: &[u8]) -> Result<Vec<u8>, &'static str> {
if data.is_empty() {
return Ok(Vec::new());
}
active()
.symmetric()
.aes_cbc_decrypt(AesKeySize::Aes128, key, iv, data, Padding::Pkcs7)
.map_err(map_err)
}
pub fn aes256_encrypt(key: &[u8], iv: &[u8], data: &[u8]) -> Result<Vec<u8>, &'static str> {
active()
.symmetric()
.aes_cbc_encrypt(AesKeySize::Aes256, key, iv, data, Padding::Pkcs7)
.map_err(map_err)
}
pub fn aes256_decrypt(key: &[u8], iv: &[u8], data: &[u8]) -> Result<Vec<u8>, &'static str> {
if data.is_empty() {
return Ok(Vec::new());
}
active()
.symmetric()
.aes_cbc_decrypt(AesKeySize::Aes256, key, iv, data, Padding::Pkcs7)
.map_err(map_err)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn aes128_encrypt_decrypt_round_trip() {
let key = b"PDF-AES-128-key!"; let iv = b"AES-IV-16-bytes!"; let plaintext = b"PDF Standard Security Handler V=4 stream content.";
let ciphertext = aes128_encrypt(key, iv, plaintext).unwrap();
let decrypted = aes128_decrypt(key, iv, &ciphertext).unwrap();
assert_eq!(decrypted, plaintext);
}
#[test]
fn aes128_encrypt_block_aligned() {
let key = [0x42u8; 16];
let iv = [0x13u8; 16];
let plaintext = [0x0au8; 16];
let ciphertext = aes128_encrypt(&key, &iv, &plaintext).unwrap();
assert_eq!(ciphertext.len(), 32, "PKCS#7 must add a full padding block");
let decrypted = aes128_decrypt(&key, &iv, &ciphertext).unwrap();
assert_eq!(decrypted, plaintext);
}
#[test]
fn aes256_no_padding_round_trip() {
let key = [0x07u8; 32];
let iv = [0u8; 16]; let plaintext = [0xa5u8; 32];
let ciphertext = aes256_encrypt_no_padding(&key, &iv, &plaintext).unwrap();
let decrypted = aes256_decrypt_no_padding(&key, &iv, &ciphertext).unwrap();
assert_eq!(decrypted, plaintext);
}
#[test]
fn aes_rejects_short_key() {
let result = aes128_encrypt(&[0u8; 8], &[0u8; 16], b"data1234data1234");
assert!(result.is_err());
}
}