Improved encryption implementation

This commit is contained in:
G2-Games 2024-08-15 00:35:01 -05:00
parent 9172a524d3
commit 833eeb6158
2 changed files with 132 additions and 117 deletions

View file

@ -9,9 +9,25 @@ use super::interface::DataEncryptorInput;
type DesEcbEnc = ecb::Decryptor<des::Des>; type DesEcbEnc = ecb::Decryptor<des::Des>;
type DesCbcEnc = cbc::Encryptor<des::Des>; type DesCbcEnc = cbc::Encryptor<des::Des>;
pub fn threaded_encryptor( pub struct Encryptor {
input: DataEncryptorInput, channel: Option<UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)>>,
) -> UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)> { state: Option<EncryptorState>,
}
struct EncryptorState {
input_data: Vec<u8>,
iv: [u8; 8],
random_key: [u8; 8],
encrypted_random_key: [u8; 8],
default_chunk_size: usize,
current_chunk_size: usize,
offset: usize,
packet_count: usize,
closed: bool,
}
impl Encryptor {
pub fn new_threaded(input: DataEncryptorInput) -> Self {
let (tx, rx) = unbounded_channel::<(Vec<u8>, Vec<u8>, Vec<u8>)>(); let (tx, rx) = unbounded_channel::<(Vec<u8>, Vec<u8>, Vec<u8>)>();
thread::spawn(move || { thread::spawn(move || {
@ -73,22 +89,12 @@ pub fn threaded_encryptor(
} }
}); });
rx Self {
channel: Some(rx),
state: None
}
} }
pub struct Encryptor {
input_data: Vec<u8>,
iv: [u8; 8],
random_key: [u8; 8],
encrypted_random_key: [u8; 8],
default_chunk_size: usize,
current_chunk_size: usize,
offset: usize,
packet_count: usize,
closed: bool,
}
impl Encryptor {
pub fn new(input: DataEncryptorInput) -> Self { pub fn new(input: DataEncryptorInput) -> Self {
let iv = [0u8; 8]; let iv = [0u8; 8];
@ -120,7 +126,9 @@ impl Encryptor {
let offset: usize = 0; let offset: usize = 0;
Self { Encryptor {
channel: None,
state: Some(EncryptorState {
input_data, input_data,
iv, iv,
random_key, random_key,
@ -130,48 +138,59 @@ impl Encryptor {
default_chunk_size, default_chunk_size,
packet_count, packet_count,
closed: false, closed: false,
})
} }
} }
/// Get the next encrypted value /// Get the next encrypted value
pub async fn next(&mut self) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>)> { pub async fn next(&mut self) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>)> {
if self.closed { let output;
if let Some(state) = self.state.as_mut() {
if state.closed {
return None return None
} }
if self.packet_count > 0 { if state.packet_count > 0 {
self.current_chunk_size = self.default_chunk_size; state.current_chunk_size = state.default_chunk_size;
} else { } else {
self.current_chunk_size = self.default_chunk_size - 24; state.current_chunk_size = state.default_chunk_size - 24;
} }
self.current_chunk_size = std::cmp::min(self.current_chunk_size, self.input_data.len() - self.offset); state.current_chunk_size = std::cmp::min(state.current_chunk_size, state.input_data.len() - state.offset);
let this_data_chunk = &mut self.input_data[self.offset..self.offset + self.current_chunk_size]; let this_data_chunk = &mut state.input_data[state.offset..state.offset + state.current_chunk_size];
DesCbcEnc::new(&self.random_key.into(), &self.iv.into()) DesCbcEnc::new(&state.random_key.into(), &state.iv.into())
.encrypt_padded_mut::<NoPadding>(this_data_chunk, self.current_chunk_size) .encrypt_padded_mut::<NoPadding>(this_data_chunk, state.current_chunk_size)
.unwrap(); .unwrap();
let output = ( output = Some((
self.encrypted_random_key.to_vec(), state.encrypted_random_key.to_vec(),
self.iv.to_vec(), state.iv.to_vec(),
this_data_chunk.to_vec(), this_data_chunk.to_vec(),
); ));
self.iv.copy_from_slice(&this_data_chunk[this_data_chunk.len() - 8..]); state.iv.copy_from_slice(&this_data_chunk[this_data_chunk.len() - 8..]);
self.packet_count += 1; state.packet_count += 1;
self.offset += self.current_chunk_size; state.offset += state.current_chunk_size;
} else if let Some(channel) = self.channel.as_mut() {
output = channel.recv().await
} else {
unreachable!("If you got here, this is bad!");
}
Some(output) output
} }
/// Call close to return none from subsequent calls /// Call close to return none from subsequent calls
pub fn close(&mut self) { pub fn close(&mut self) {
self.closed = true; if let Some(state) = self.state.as_mut() {
state.closed = true;
} else if let Some(channel) = self.channel.as_mut() {
channel.close()
} else {
unreachable!("If you got here, this is bad!");
} }
} }
pub fn encryptor() {
} }

View file

@ -17,7 +17,7 @@ use std::time::Duration;
use thiserror::Error; use thiserror::Error;
use super::base::NetMD; use super::base::NetMD;
use super::encryption::{threaded_encryptor, EncryptorState}; use super::encryption::Encryptor;
use super::utils::{cross_sleep, to_sjis}; use super::utils::{cross_sleep, to_sjis};
/// An action to take on the player /// An action to take on the player
@ -1690,11 +1690,7 @@ impl NetMDInterface {
discformat: u8, discformat: u8,
frames: u32, frames: u32,
pkt_size: u32, pkt_size: u32,
// key, iv, data mut packets: Encryptor,
#[cfg(not(target_family = "wasm"))]
mut packets: UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)>,
#[cfg(target_family = "wasm")]
mut packets: EncryptorState,
hex_session_key: &[u8], hex_session_key: &[u8],
progress_callback: F, progress_callback: F,
) -> Result<(u16, Vec<u8>, Vec<u8>), InterfaceError> ) -> Result<(u16, Vec<u8>, Vec<u8>), InterfaceError>
@ -1733,7 +1729,7 @@ impl NetMDInterface {
let mut written_bytes = 0; let mut written_bytes = 0;
let mut packet_count = 0; let mut packet_count = 0;
while let Some((key, iv, data)) = packets.recv().await { while let Some((key, iv, data)) = packets.next().await {
let binpack = if packet_count == 0 { let binpack = if packet_count == 0 {
let packed_length: Vec<u8> = pkt_size.to_be_bytes().to_vec(); let packed_length: Vec<u8> = pkt_size.to_be_bytes().to_vec();
[vec![0, 0, 0, 0], packed_length, key, iv, data].concat() [vec![0, 0, 0, 0], packed_length, key, iv, data].concat()
@ -1921,8 +1917,8 @@ impl MDTrack {
} }
#[cfg(not(target_family = "wasm"))] #[cfg(not(target_family = "wasm"))]
pub fn get_encrypting_iterator(&mut self) -> UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)> { pub fn get_encrypting_iterator(&mut self) -> Encryptor {
threaded_encryptor(DataEncryptorInput { Encryptor::new_threaded(DataEncryptorInput {
kek: self.get_kek(), kek: self.get_kek(),
frame_size: self.frame_size(), frame_size: self.frame_size(),
chunk_size: self.chunk_size(), chunk_size: self.chunk_size(),
@ -1931,8 +1927,8 @@ impl MDTrack {
} }
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
pub fn get_encrypting_iterator(&mut self) -> EncryptorState { pub fn get_encrypting_iterator(&mut self) -> Encryptor {
EncryptorState::new(DataEncryptorInput { Encryptor::new(DataEncryptorInput {
kek: self.get_kek(), kek: self.get_kek(),
frame_size: self.frame_size(), frame_size: self.frame_size(),
chunk_size: self.chunk_size(), chunk_size: self.chunk_size(),