#![allow(deprecated)]
use crate::error::{BotError, BotResult};
use aes::cipher::{BlockDecrypt, BlockEncrypt, KeyInit};
use aes::Aes128;
use cipher::generic_array::GenericArray;
use xbw::crypt::{
base64::{Base64, Engine},
hex,
};
const BLOCK_SIZE: usize = 16;
pub fn parse_aes_key(key_str: &str) -> BotResult<[u8; 16]> {
let raw = key_str.trim();
if [32, 48, 64].contains(&raw.len()) && raw.chars().all(|c| c.is_ascii_hexdigit()) {
let bytes = hex::decode(raw)?;
if bytes.len() == 16 {
return Ok(arraycopy(&bytes));
}
}
let decoded = Base64
.decode(raw)
.unwrap_or_else(|_| raw.as_bytes().to_vec());
if decoded.len() == 16 {
return Ok(arraycopy(&decoded));
}
if decoded.len() == 32 && decoded.iter().all(|&b| b.is_ascii_hexdigit()) {
let bytes = hex::decode(&decoded)?;
if bytes.len() == 16 {
return Ok(arraycopy(&bytes));
}
}
Err(BotError::invalid_data(format!(
"无法解析 AES 密钥: raw={:?} len={}",
&raw.chars().take(20).collect::<String>(),
raw.len()
)))
}
pub fn aes_ecb_decrypt(data: &[u8], aes_key: &str) -> BotResult<Vec<u8>> {
let key = parse_aes_key(aes_key)?;
let cipher = Aes128::new_from_slice(&key)
.map_err(|e| BotError::crypto(format!("AES 密钥初始化失败: {:?}", e)))?;
if data.len() % BLOCK_SIZE != 0 {
return Err(BotError::invalid_data(format!(
"加密数据长度 {} 不是块大小 {} 的整数倍",
data.len(),
BLOCK_SIZE
)));
}
let mut buf = data.to_vec();
for chunk in buf.chunks_mut(BLOCK_SIZE) {
let block = GenericArray::from_mut_slice(chunk);
cipher.decrypt_block(block);
}
let pad_byte = buf.last().copied().unwrap_or(0) as usize;
if pad_byte == 0 || pad_byte > BLOCK_SIZE {
return Err(BotError::invalid_data(format!(
"无效的 PKCS7 填充字节: {}",
pad_byte
)));
}
for &b in &buf[buf.len() - pad_byte..] {
if b as usize != pad_byte {
return Err(BotError::invalid_data(format!(
"PKCS7 填充校验失败: 期望 {pad_byte},实际得到 {b}"
)));
}
}
buf.truncate(buf.len() - pad_byte);
Ok(buf)
}
pub fn aes_ecb_encrypt(data: &[u8], key: &[u8; 16]) -> BotResult<Vec<u8>> {
let cipher = Aes128::new_from_slice(key)
.map_err(|e| BotError::crypto(format!("AES 密钥初始化失败: {:?}", e)))?;
let padding = BLOCK_SIZE - (data.len() % BLOCK_SIZE);
let padded_len = data.len() + padding;
let mut buf = vec![0u8; padded_len];
buf[..data.len()].copy_from_slice(data);
buf[data.len()..].fill(padding as u8);
for chunk in buf.chunks_mut(BLOCK_SIZE) {
let block = GenericArray::from_mut_slice(chunk);
cipher.encrypt_block(block);
}
Ok(buf)
}
fn arraycopy(src: &[u8]) -> [u8; 16] {
let mut dst = [0u8; 16];
dst.copy_from_slice(src);
dst
}