mirror of
https://github.com/G2-Games/minidisc-cli.git
synced 2025-04-19 19:52:53 -05:00
Initial untested experiment
This commit is contained in:
parent
885e7508fd
commit
7935c5386d
4 changed files with 123 additions and 18 deletions
|
@ -3,4 +3,4 @@ rustflags = ["--cfg=web_sys_unstable_apis"]
|
|||
|
||||
# Enable for testing WASM-only stuff
|
||||
[build]
|
||||
#target = "wasm32-unknown-unknown"
|
||||
target = "wasm32-unknown-unknown"
|
||||
|
|
|
@ -45,13 +45,16 @@ getrandom = { version = "0.2", features = ["js"] }
|
|||
des = "0.8"
|
||||
cbc = "0.1"
|
||||
ecb = "0.1"
|
||||
tokio = { version = "1.36", features = ["sync"] }
|
||||
g2-unicode-jp = "0.4.1"
|
||||
thiserror = "1.0.57"
|
||||
phf = { version = "0.11.2", features = ["phf_macros", "macros"] }
|
||||
byteorder = "1.5.0"
|
||||
log = "0.4.22"
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||
tokio = { version = "1.36", features = ["sync"] }
|
||||
|
||||
[target.'cfg(target_family = "wasm")'.dependencies]
|
||||
gloo = { version = "0.11.0", features = ["futures", "worker"] }
|
||||
futures = "0.3.30"
|
||||
gloo = { version = "0.11", features = ["futures", "worker"] }
|
||||
futures = "0.3"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
use cbc::cipher::block_padding::NoPadding;
|
||||
use cbc::cipher::{BlockDecryptMut, BlockEncryptMut, KeyInit, KeyIvInit};
|
||||
use rand::RngCore;
|
||||
use super::interface::DataEncryptorInput;
|
||||
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
use std::thread;
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
|
||||
|
||||
use super::interface::DataEncryptorInput;
|
||||
#[cfg(target_family = "wasm")]
|
||||
use futures::{SinkExt, StreamExt};
|
||||
#[cfg(target_family = "wasm")]
|
||||
use gloo::worker::reactor::{reactor, ReactorBridge, ReactorScope};
|
||||
|
||||
type DesEcbEnc = ecb::Decryptor<des::Des>;
|
||||
type DesCbcEnc = cbc::Encryptor<des::Des>;
|
||||
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
pub fn new_thread_encryptor(
|
||||
_input: DataEncryptorInput,
|
||||
input: DataEncryptorInput,
|
||||
) -> UnboundedReceiver<(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 || {
|
||||
let _ = thread::spawn(move || {
|
||||
let mut iv = [0u8; 8];
|
||||
|
||||
// Create the random key
|
||||
|
@ -76,3 +83,81 @@ pub fn new_thread_encryptor(
|
|||
|
||||
rx
|
||||
}
|
||||
|
||||
|
||||
#[cfg(target_family = "wasm")]
|
||||
pub fn web_worker_encryptor(
|
||||
input: DataEncryptorInput,
|
||||
) -> ReactorBridge<WebThread> {
|
||||
use gloo::worker::Spawnable;
|
||||
|
||||
let bridge = WebThread::spawner().spawn("...");
|
||||
bridge.send_input(input);
|
||||
|
||||
bridge
|
||||
}
|
||||
|
||||
#[cfg(target_family = "wasm")]
|
||||
#[reactor]
|
||||
pub async fn WebThread(
|
||||
mut scope: ReactorScope<DataEncryptorInput, (Vec<u8>, Vec<u8>, Vec<u8>)>
|
||||
) {
|
||||
// Get the initial input data
|
||||
let input = scope.next().await.unwrap();
|
||||
|
||||
let mut 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 mut packet_count = 0u32;
|
||||
let mut current_chunk_size;
|
||||
|
||||
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 input_data_length = input_data.len();
|
||||
|
||||
let mut offset: usize = 0;
|
||||
while offset < input_data_length {
|
||||
if packet_count > 0 {
|
||||
current_chunk_size = default_chunk_size;
|
||||
} else {
|
||||
current_chunk_size = default_chunk_size - 24;
|
||||
}
|
||||
|
||||
current_chunk_size = std::cmp::min(current_chunk_size, input_data_length - offset);
|
||||
|
||||
let this_data_chunk = &mut input_data[offset..offset + current_chunk_size];
|
||||
DesCbcEnc::new(&random_key.into(), &iv.into())
|
||||
.encrypt_padded_mut::<NoPadding>(this_data_chunk, current_chunk_size)
|
||||
.unwrap();
|
||||
|
||||
scope.send((
|
||||
encrypted_random_key.to_vec(),
|
||||
iv.to_vec(),
|
||||
this_data_chunk.to_vec(),
|
||||
)).await.unwrap();
|
||||
|
||||
iv.copy_from_slice(&this_data_chunk[this_data_chunk.len() - 8..]);
|
||||
|
||||
packet_count += 1;
|
||||
offset += current_chunk_size;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ use std::collections::HashMap;
|
|||
use std::error::Error;
|
||||
use std::time::Duration;
|
||||
use thiserror::Error;
|
||||
use tokio::sync::mpsc::UnboundedReceiver;
|
||||
|
||||
use super::base::NetMD;
|
||||
use super::utils::{cross_sleep, to_sjis};
|
||||
|
@ -1691,7 +1690,10 @@ impl NetMDInterface {
|
|||
frames: u32,
|
||||
pkt_size: u32,
|
||||
// key, iv, data
|
||||
mut packets: UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)>,
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
mut packets: tokio::sync::mpsc::UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)>,
|
||||
#[cfg(target_family = "wasm")]
|
||||
mut packets: gloo::worker::reactor::ReactorBridge<super::encryption::WebThread>,
|
||||
hex_session_key: &[u8],
|
||||
progress_callback: F,
|
||||
) -> Result<(u16, Vec<u8>, Vec<u8>), InterfaceError>
|
||||
|
@ -1730,7 +1732,15 @@ impl NetMDInterface {
|
|||
let mut written_bytes = 0;
|
||||
let mut packet_count = 0;
|
||||
|
||||
while let Some((key, iv, data)) = packets.recv().await {
|
||||
while let Some((key, iv, data)) = {
|
||||
{
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
packets.recv().await
|
||||
}
|
||||
|
||||
#[cfg(target_family = "wasm")]
|
||||
futures::StreamExt::next(&mut packets).await
|
||||
} {
|
||||
let binpack = if packet_count == 0 {
|
||||
let packed_length: Vec<u8> = pkt_size.to_be_bytes().to_vec();
|
||||
[vec![0, 0, 0, 0], packed_length, key, iv, data].concat()
|
||||
|
@ -1742,7 +1752,6 @@ impl NetMDInterface {
|
|||
packet_count += 1;
|
||||
(progress_callback)(total_bytes, written_bytes);
|
||||
if total_bytes == written_bytes {
|
||||
packets.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1863,12 +1872,9 @@ pub struct MDTrack {
|
|||
pub data: Vec<u8>,
|
||||
pub chunk_size: usize,
|
||||
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>)>>,
|
||||
}
|
||||
|
||||
#[cfg_attr(target_family = "wasm", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct DataEncryptorInput {
|
||||
pub kek: [u8; 8],
|
||||
pub frame_size: usize,
|
||||
|
@ -1921,8 +1927,19 @@ impl MDTrack {
|
|||
[0x14, 0xe3, 0x83, 0x4e, 0xe2, 0xd3, 0xcc, 0xa5]
|
||||
}
|
||||
|
||||
pub fn get_encrypting_iterator(&mut self) -> UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)> {
|
||||
(self.encrypt_packets_iterator)(DataEncryptorInput {
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
pub fn get_encrypting_iterator(&mut self) -> tokio::sync::mpsc::UnboundedReceiver<(Vec<u8>, Vec<u8>, Vec<u8>)> {
|
||||
super::encryption::new_thread_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) -> gloo::worker::reactor::ReactorBridge<super::encryption::WebThread> {
|
||||
super::encryption::web_worker_encryptor(DataEncryptorInput {
|
||||
kek: self.get_kek(),
|
||||
frame_size: self.frame_size(),
|
||||
chunk_size: self.chunk_size(),
|
||||
|
|
Loading…
Reference in a new issue