Initial working WASM encryption

This commit is contained in:
G2-Games 2024-08-15 00:04:55 -05:00
parent 885e7508fd
commit 9172a524d3
2 changed files with 118 additions and 9 deletions

View file

@ -9,11 +9,10 @@ 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 new_thread_encryptor( pub fn threaded_encryptor(
_input: DataEncryptorInput, input: DataEncryptorInput,
) -> UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)> { ) -> UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)> {
let (tx, rx) = unbounded_channel::<(Vec<u8>, Vec<u8>, Vec<u8>)>(); let (tx, rx) = unbounded_channel::<(Vec<u8>, Vec<u8>, Vec<u8>)>();
let input = Box::from(_input);
thread::spawn(move || { thread::spawn(move || {
let mut iv = [0u8; 8]; let mut iv = [0u8; 8];
@ -76,3 +75,103 @@ pub fn new_thread_encryptor(
rx rx
} }
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 {
let iv = [0u8; 8];
// Create the random key
let mut random_key = [0u8; 8];
rand::thread_rng().fill_bytes(&mut random_key);
// Encrypt it with the kek
let mut encrypted_random_key = random_key;
if let Err(x) = DesEcbEnc::new(&input.kek.into())
.decrypt_padded_mut::<NoPadding>(&mut encrypted_random_key)
{
panic!("Cannot create main key {:?}", x)
};
let default_chunk_size = match input.chunk_size {
0 => 0x00100000,
e => e,
};
let packet_count = 0;
let current_chunk_size = 0;
let mut input_data = input.data.clone();
if (input_data.len() % input.frame_size) != 0 {
let padding_remaining = input.frame_size - (input_data.len() % input.frame_size);
input_data.extend(std::iter::repeat(0).take(padding_remaining));
}
let offset: usize = 0;
Self {
input_data,
iv,
random_key,
encrypted_random_key,
current_chunk_size,
offset,
default_chunk_size,
packet_count,
closed: false,
}
}
/// Get the next encrypted value
pub async fn next(&mut self) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>)> {
if self.closed {
return None
}
if self.packet_count > 0 {
self.current_chunk_size = self.default_chunk_size;
} else {
self.current_chunk_size = self.default_chunk_size - 24;
}
self.current_chunk_size = std::cmp::min(self.current_chunk_size, self.input_data.len() - self.offset);
let this_data_chunk = &mut self.input_data[self.offset..self.offset + self.current_chunk_size];
DesCbcEnc::new(&self.random_key.into(), &self.iv.into())
.encrypt_padded_mut::<NoPadding>(this_data_chunk, self.current_chunk_size)
.unwrap();
let output = (
self.encrypted_random_key.to_vec(),
self.iv.to_vec(),
this_data_chunk.to_vec(),
);
self.iv.copy_from_slice(&this_data_chunk[this_data_chunk.len() - 8..]);
self.packet_count += 1;
self.offset += self.current_chunk_size;
Some(output)
}
/// Call close to return none from subsequent calls
pub fn close(&mut self) {
self.closed = true;
}
}
pub fn encryptor() {
}

View file

@ -15,9 +15,9 @@ use std::collections::HashMap;
use std::error::Error; use std::error::Error;
use std::time::Duration; use std::time::Duration;
use thiserror::Error; use thiserror::Error;
use tokio::sync::mpsc::UnboundedReceiver;
use super::base::NetMD; use super::base::NetMD;
use super::encryption::{threaded_encryptor, EncryptorState};
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
@ -1691,7 +1691,10 @@ impl NetMDInterface {
frames: u32, frames: u32,
pkt_size: u32, pkt_size: u32,
// key, iv, data // key, iv, data
#[cfg(not(target_family = "wasm"))]
mut packets: UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)>, 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>
@ -1863,10 +1866,6 @@ pub struct MDTrack {
pub data: Vec<u8>, pub data: Vec<u8>,
pub chunk_size: usize, pub chunk_size: usize,
pub full_width_title: Option<String>, pub full_width_title: Option<String>,
#[allow(clippy::type_complexity)]
pub encrypt_packets_iterator:
Box<dyn Fn(DataEncryptorInput) -> UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)>>,
} }
pub struct DataEncryptorInput { pub struct DataEncryptorInput {
@ -1921,8 +1920,19 @@ impl MDTrack {
[0x14, 0xe3, 0x83, 0x4e, 0xe2, 0xd3, 0xcc, 0xa5] [0x14, 0xe3, 0x83, 0x4e, 0xe2, 0xd3, 0xcc, 0xa5]
} }
#[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) -> UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)> {
(self.encrypt_packets_iterator)(DataEncryptorInput { threaded_encryptor(DataEncryptorInput {
kek: self.get_kek(),
frame_size: self.frame_size(),
chunk_size: self.chunk_size(),
data: std::mem::take(&mut self.data),
})
}
#[cfg(target_family = "wasm")]
pub fn get_encrypting_iterator(&mut self) -> EncryptorState {
EncryptorState::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(),