use crate::wrath_header::{
ClientHeader, ServerHeader, CLIENT_HEADER_LENGTH, R, S, SERVER_HEADER_MAXIMUM_LENGTH,
SERVER_HEADER_MINIMUM_LENGTH,
};
use crate::SESSION_KEY_LENGTH;
use crate::wrath_header::inner_crypto::InnerCrypto;
use std::io::Read;
#[derive(Debug)]
pub struct ServerDecrypterHalf {
decrypt: InnerCrypto,
}
impl ServerDecrypterHalf {
pub fn decrypt(&mut self, data: &mut [u8]) {
self.decrypt.apply(data);
}
pub fn read_and_decrypt_client_header<R: Read>(
&mut self,
reader: &mut R,
) -> std::io::Result<ClientHeader> {
let mut buf = [0_u8; CLIENT_HEADER_LENGTH as usize];
reader.read_exact(&mut buf)?;
Ok(self.decrypt_client_header(buf))
}
pub fn decrypt_client_header(
&mut self,
mut data: [u8; CLIENT_HEADER_LENGTH as usize],
) -> ClientHeader {
self.decrypt(&mut data);
let size: u16 = u16::from_be_bytes([data[0], data[1]]);
let opcode: u32 = u32::from_le_bytes([data[2], data[3], data[4], data[5]]);
ClientHeader { size, opcode }
}
pub(crate) fn new(session_key: [u8; SESSION_KEY_LENGTH as usize]) -> Self {
Self {
decrypt: InnerCrypto::new(session_key, &S),
}
}
}
#[derive(Debug)]
pub struct ClientDecrypterHalf {
decrypt: InnerCrypto,
}
impl ClientDecrypterHalf {
pub fn decrypt(&mut self, data: &mut [u8]) {
self.decrypt.apply(data);
}
pub fn decrypt_server_header(
&mut self,
data: &[u8; SERVER_HEADER_MAXIMUM_LENGTH as usize],
) -> ServerHeader {
let mut copied_data = *data;
self.decrypt.apply(&mut copied_data[0..1]);
if copied_data[0] & 0x80 != 0 {
self.decrypt(&mut copied_data[1..]);
let most_significant_byte = copied_data[0] & 0x7F;
let size =
u32::from_be_bytes([0, most_significant_byte, copied_data[1], copied_data[2]]);
let opcode = u16::from_le_bytes([copied_data[3], copied_data[4]]);
ServerHeader { size, opcode }
} else {
self.decrypt(&mut copied_data[1..SERVER_HEADER_MINIMUM_LENGTH as usize]);
let size = u16::from_be_bytes([copied_data[0], copied_data[1]]);
let opcode = u16::from_le_bytes([copied_data[2], copied_data[3]]);
ServerHeader {
size: size.into(),
opcode,
}
}
}
pub(crate) fn new(session_key: [u8; SESSION_KEY_LENGTH as usize]) -> Self {
Self {
decrypt: InnerCrypto::new(session_key, &R),
}
}
}