use crate::pack::utils::ciphers::{
decrypt_cbc, decrypt_ecb,
encrypt_cbc, encrypt_ecb,
get_md5_key
};
use crate::pack::utils::verify;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Region {
En,
Jp,
Kr,
Tw,
}
pub struct PackKeys {
pub tuples: Vec<(String, String, Region)>,
}
pub fn decrypt_pack_chunk(
data: &[u8],
internal_filename: &str,
keys: &PackKeys
) -> Result<(Vec<u8>, Option<Region>), String> {
for (k_hex, iv_hex, region) in &keys.tuples {
let Ok(key_bytes) = hex::decode(k_hex) else { continue; };
let Ok(iv_bytes) = hex::decode(iv_hex) else { continue; };
let (Ok(key_arr), Ok(iv_arr)) = (key_bytes.try_into(), iv_bytes.try_into()) else { continue; };
if let Ok(result) = decrypt_cbc(data, &key_arr, &iv_arr) {
if verify::is_valid(&result, internal_filename) {
return Ok((result, Some(*region)));
}
}
}
let server_key = get_md5_key("battlecats");
if let Ok(result) = decrypt_ecb(data, &server_key) {
if verify::is_valid(&result, internal_filename) {
return Ok((result, None));
}
}
Ok((data.to_vec(), None))
}
pub fn decrypt_list(data: &[u8]) -> Result<String, String> {
let pack_key = get_md5_key("pack");
if let Ok(bytes) = decrypt_ecb(data, &pack_key) {
if let Ok(s) = String::from_utf8(bytes) { return Ok(s); }
}
let bc_key = get_md5_key("battlecats");
if let Ok(bytes) = decrypt_ecb(data, &bc_key) {
if let Ok(s) = String::from_utf8(bytes) { return Ok(s); }
}
Err("List decryption failed (Invalid keys or corrupted file)".into())
}
pub fn encrypt_list(data: &str) -> Result<Vec<u8>, String> {
let pack_key = get_md5_key("pack");
encrypt_ecb(data.as_bytes(), &pack_key)
}
pub fn encrypt_server_data(data: &[u8]) -> Result<Vec<u8>, String> {
let server_key = get_md5_key("battlecats");
encrypt_ecb(data, &server_key)
}
pub fn encrypt_game_data(data: &[u8], key: &[u8; 16], iv: &[u8; 16]) -> Result<Vec<u8>, String> {
encrypt_cbc(data, key, iv)
}