From f076764fff6455253da4454e5e371bfc688bb40c Mon Sep 17 00:00:00 2001 From: "NGnius (Graham)" Date: Sun, 24 Jul 2022 14:45:48 -0400 Subject: [PATCH] Add experimental encryption support --- Cargo.lock | 116 +++++++++++++++++++++++++++++++- usdpl-back/Cargo.toml | 9 ++- usdpl-back/src/instance.rs | 49 ++++++++++++++ usdpl-core/Cargo.toml | 7 +- usdpl-core/src/serdes/traits.rs | 50 ++++++++++++++ usdpl-core/src/socket.rs | 37 ++++++++++ usdpl-front/Cargo.toml | 8 ++- usdpl-front/build.sh | 6 +- usdpl-front/src/connection.rs | 53 +++++++++++++-- usdpl-front/src/lib.rs | 22 +++++- 10 files changed, 339 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a182c29..3c36bbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,42 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if 1.0.0", + "cipher", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589c637f0e68c877bbd59a4599bbe849cac8e5f3e4b5a3ebae8f528cd218dcdc" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "polyval", + "subtle", + "zeroize", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -78,6 +114,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -107,6 +152,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher", +] + [[package]] name = "digest" version = "0.9.0" @@ -273,6 +327,18 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "http" version = "0.2.8" @@ -471,6 +537,12 @@ dependencies = [ "libc", ] +[[package]] +name = "obfstr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2b2cbbfd8defa51ff24450a61d73b3ff3e158484ddd274a883e886e6fbaa78" + [[package]] name = "once_cell" version = "1.13.0" @@ -521,6 +593,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.16" @@ -686,6 +770,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" version = "1.0.98" @@ -912,6 +1002,16 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "url" version = "2.2.2" @@ -926,9 +1026,11 @@ dependencies = [ [[package]] name = "usdpl-back" -version = "0.5.3" +version = "0.6.0" dependencies = [ "bytes", + "hex", + "obfstr", "tokio", "usdpl-core", "warp", @@ -936,9 +1038,11 @@ dependencies = [ [[package]] name = "usdpl-core" -version = "0.5.0" +version = "0.6.0" dependencies = [ + "aes-gcm-siv", "base64", + "hex-literal", ] [[package]] @@ -946,7 +1050,9 @@ name = "usdpl-front" version = "0.5.0" dependencies = [ "console_error_panic_hook", + "hex", "js-sys", + "obfstr", "usdpl-core", "wasm-bindgen", "wasm-bindgen-futures", @@ -1193,3 +1299,9 @@ name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" diff --git a/usdpl-back/Cargo.toml b/usdpl-back/Cargo.toml index 95bedaf..7c98345 100644 --- a/usdpl-back/Cargo.toml +++ b/usdpl-back/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "usdpl-back" -version = "0.5.3" +version = "0.6.0" edition = "2021" license = "GPL-3.0-only" repository = "https://github.com/NGnius/usdpl-rs" @@ -12,11 +12,16 @@ default = ["blocking"] decky = ["usdpl-core/decky"] crankshaft = ["usdpl-core/crankshaft"] blocking = ["tokio"] # synchronous API for async functionality, using tokio +encrypt = ["usdpl-core/encrypt", "obfstr", "hex"] [dependencies] -usdpl-core = { version = "0.5.0", path = "../usdpl-core" } +usdpl-core = { version = "0.6.0", path = "../usdpl-core"} # HTTP web framework warp = { version = "0.3" } bytes = { version = "1.1" } tokio = { version = "1.19", features = ["rt", "rt-multi-thread"], optional = true } + +# encryption helpers +obfstr = { version = "0.3", optional = true } +hex = { version = "0.4", optional = true } diff --git a/usdpl-back/src/instance.rs b/usdpl-back/src/instance.rs index 202df6f..89d2ed6 100644 --- a/usdpl-back/src/instance.rs +++ b/usdpl-back/src/instance.rs @@ -11,10 +11,15 @@ use super::Callable; type WrappedCallable = Arc>>; // thread-safe, cloneable Callable +#[cfg(feature = "encrypt")] +const NONCE: [u8; socket::NONCE_SIZE] = [0u8; socket::NONCE_SIZE]; + /// Back-end instance for interacting with the front-end pub struct Instance { calls: HashMap, port: u16, + #[cfg(feature = "encrypt")] + encryption_key: Vec, } impl Instance { @@ -24,6 +29,8 @@ impl Instance { Instance { calls: HashMap::new(), port: port_usdpl, + #[cfg(feature = "encrypt")] + encryption_key: hex::decode(obfstr::obfstr!(env!("USDPL_ENCRYPTION_KEY"))).unwrap(), } } @@ -100,6 +107,7 @@ impl Instance { async fn serve_internal(&self) -> Result<(), ()> { let handlers = self.calls.clone(); //self.calls = HashMap::new(); + #[cfg(not(feature = "encrypt"))] let calls = warp::post() .and(warp::path!("usdpl" / "call")) .and(warp::body::content_length_limit( @@ -136,6 +144,47 @@ impl Instance { ) }) .map(|reply| warp::reply::with_header(reply, "Access-Control-Allow-Origin", "*")); + #[cfg(feature = "encrypt")] + let key = self.encryption_key.clone(); + #[cfg(feature = "encrypt")] + let calls = warp::post() + .and(warp::path!("usdpl" / "call")) + .and(warp::body::content_length_limit( + (socket::PACKET_BUFFER_SIZE * 2) as _, + )) + .and(warp::body::bytes()) + .map(move |data: bytes::Bytes| { + let (packet, _) = match socket::Packet::load_encrypted(&data, &key, &NONCE) { + Ok(x) => x, + Err(_) => { + return warp::reply::with_status( + warp::http::Response::builder() + .body("Failed to load packet".to_string()), + warp::http::StatusCode::from_u16(400).unwrap(), + ) + } + }; + let mut buffer = Vec::with_capacity(socket::PACKET_BUFFER_SIZE); + buffer.extend(&[0u8; socket::PACKET_BUFFER_SIZE]); + let response = Self::handle_call(packet, &handlers); + let len = match response.dump_encrypted(&mut buffer, &key, &NONCE) { + Ok(x) => x, + Err(_) => { + return warp::reply::with_status( + warp::http::Response::builder() + .body("Failed to dump response packet".to_string()), + warp::http::StatusCode::from_u16(500).unwrap(), + ) + } + }; + buffer.truncate(len); + let string: String = String::from_utf8(buffer).unwrap().into(); + warp::reply::with_status( + warp::http::Response::builder().body(string), + warp::http::StatusCode::from_u16(200).unwrap(), + ) + }) + .map(|reply| warp::reply::with_header(reply, "Access-Control-Allow-Origin", "*")); #[cfg(debug_assertions)] warp::serve(calls).run(([0, 0, 0, 0], self.port)).await; #[cfg(not(debug_assertions))] diff --git a/usdpl-core/Cargo.toml b/usdpl-core/Cargo.toml index a9bbcaf..c0624e2 100644 --- a/usdpl-core/Cargo.toml +++ b/usdpl-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "usdpl-core" -version = "0.5.0" +version = "0.6.0" edition = "2021" license = "GPL-3.0-only" repository = "https://github.com/NGnius/usdpl-rs" @@ -11,6 +11,11 @@ description = "Universal Steam Deck Plugin Library core" default = [] decky = [] crankshaft = [] +encrypt = ["aes-gcm-siv"] [dependencies] base64 = "0.13" +aes-gcm-siv = { version = "0.10", optional = true, default-features = false, features = ["alloc", "aes"] } + +[dev-dependencies] +hex-literal = "0.3.4" diff --git a/usdpl-core/src/serdes/traits.rs b/usdpl-core/src/serdes/traits.rs index a0eb482..db6967f 100644 --- a/usdpl-core/src/serdes/traits.rs +++ b/usdpl-core/src/serdes/traits.rs @@ -2,6 +2,12 @@ use base64::{decode_config_slice, encode_config_slice, Config}; const B64_CONF: Config = Config::new(base64::CharacterSet::Standard, true); +#[cfg(feature = "encrypt")] +const ASSOCIATED_DATA: &[u8] = b"usdpl-core-data"; + +#[cfg(feature = "encrypt")] +use aes_gcm_siv::aead::{AeadInPlace, NewAead}; + /// Errors from Loadable::load #[derive(Debug)] pub enum LoadError { @@ -9,6 +15,9 @@ pub enum LoadError { TooSmallBuffer, /// Unexpected/corrupted data encountered InvalidData, + /// Encrypted data cannot be decrypted + #[cfg(feature = "encrypt")] + DecryptionError, /// Unimplemented #[cfg(debug_assertions)] Todo, @@ -19,6 +28,8 @@ impl std::fmt::Display for LoadError { match self { Self::TooSmallBuffer => write!(f, "LoadError: TooSmallBuffer"), Self::InvalidData => write!(f, "LoadError: InvalidData"), + #[cfg(feature = "encrypt")] + Self::DecryptionError => write!(f, "LoadError: DecryptionError"), #[cfg(debug_assertions)] Self::Todo => write!(f, "LoadError: TODO!"), } @@ -38,6 +49,21 @@ pub trait Loadable: Sized { .map_err(|_| LoadError::InvalidData)?; Self::load(&buffer2[..len]) } + + /// Load data from an encrypted base64-encoded buffer + #[cfg(feature = "encrypt")] + fn load_encrypted(buffer: &[u8], key: &[u8], nonce: &[u8]) -> Result<(Self, usize), LoadError> { + println!("encrypted buffer: {}", String::from_utf8(buffer.to_vec()).unwrap()); + let key = aes_gcm_siv::Key::from_slice(key); + let cipher = aes_gcm_siv::Aes256GcmSiv::new(key); + let nonce = aes_gcm_siv::Nonce::from_slice(nonce); + let mut decoded_buf = base64::decode_config(buffer, B64_CONF) + .map_err(|_| LoadError::InvalidData)?; + println!("Decoded buf: {:?}", decoded_buf); + cipher.decrypt_in_place(nonce, ASSOCIATED_DATA, &mut decoded_buf).map_err(|_| LoadError::DecryptionError)?; + println!("Decrypted buf: {:?}", decoded_buf); + Self::load(decoded_buf.as_slice()) + } } /// Errors from Dumpable::dump @@ -47,6 +73,9 @@ pub enum DumpError { TooSmallBuffer, /// Data cannot be dumped Unsupported, + /// Data cannot be encrypted + #[cfg(feature = "encrypt")] + EncryptionError, /// Unimplemented #[cfg(debug_assertions)] Todo, @@ -57,6 +86,8 @@ impl std::fmt::Display for DumpError { match self { Self::TooSmallBuffer => write!(f, "DumpError: TooSmallBuffer"), Self::Unsupported => write!(f, "DumpError: Unsupported"), + #[cfg(feature = "encrypt")] + Self::EncryptionError => write!(f, "DumpError: EncryptionError"), #[cfg(debug_assertions)] Self::Todo => write!(f, "DumpError: TODO!"), } @@ -77,4 +108,23 @@ pub trait Dumpable { let len = encode_config_slice(&buffer2[..len], B64_CONF, buffer); Ok(len) } + + /// Dump data as an encrypted base64-encoded buffer + #[cfg(feature = "encrypt")] + fn dump_encrypted(&self, buffer: &mut Vec, key: &[u8], nonce: &[u8]) -> Result { + let mut buffer2 = Vec::with_capacity(buffer.capacity()); + buffer2.extend_from_slice(buffer.as_slice()); + let size = self.dump(&mut buffer2)?; + buffer2.truncate(size); + println!("Buf: {:?}", buffer2); + let key = aes_gcm_siv::Key::from_slice(key); + let cipher = aes_gcm_siv::Aes256GcmSiv::new(key); + let nonce = aes_gcm_siv::Nonce::from_slice(nonce); + cipher.encrypt_in_place(nonce, ASSOCIATED_DATA, &mut buffer2).map_err(|_| DumpError::EncryptionError)?; + println!("Encrypted slice: {:?}", &buffer2); + let size = encode_config_slice(buffer2.as_slice(), B64_CONF, buffer); + let string = String::from_utf8(buffer.as_slice()[..size].to_vec()).unwrap(); + println!("Encoded slice: {}", string); + Ok(size) + } } diff --git a/usdpl-core/src/socket.rs b/usdpl-core/src/socket.rs index bad4038..dbe35f6 100644 --- a/usdpl-core/src/socket.rs +++ b/usdpl-core/src/socket.rs @@ -11,6 +11,8 @@ pub const HOST: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); /// Standard max packet size pub const PACKET_BUFFER_SIZE: usize = 1024; +/// Encryption nonce size +pub const NONCE_SIZE: usize = 12; /// Address and port #[inline] @@ -108,3 +110,38 @@ impl Dumpable for Packet { Ok(result) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[cfg(feature = "encrypt")] + #[test] + fn encryption_integration_test() { + let key = hex_literal::hex!("59C4E408F27250B3147E7724511824F1D28ED7BEF43CF7103ACE747F77A2B265"); + let nonce = [0u8; NONCE_SIZE]; + let packet = Packet::Call(RemoteCall{ + id: 42, + function: "test".into(), + parameters: Vec::new(), + }); + let mut buffer = Vec::with_capacity(PACKET_BUFFER_SIZE); + buffer.extend_from_slice(&[0u8; PACKET_BUFFER_SIZE]); + let len = packet.dump_encrypted(&mut buffer, &key, &nonce).unwrap(); + println!("buffer: {}", String::from_utf8(buffer.as_slice()[..len].to_vec()).unwrap()); + + let (packet_out, _len) = Packet::load_encrypted(&buffer.as_slice()[..len], &key, &nonce).unwrap(); + + if let Packet::Call(call_out) = packet_out { + if let Packet::Call(call_in) = packet { + assert_eq!(call_in.id, call_out.id, "Input and output packets do not match"); + assert_eq!(call_in.function, call_out.function, "Input and output packets do not match"); + assert_eq!(call_in.parameters.len(), call_out.parameters.len(), "Input and output packets do not match"); + } else { + panic!("Packet in not a Call"); + } + } else { + panic!("Packet out not a Call!"); + } + } +} diff --git a/usdpl-front/Cargo.toml b/usdpl-front/Cargo.toml index 86575a9..23a2542 100644 --- a/usdpl-front/Cargo.toml +++ b/usdpl-front/Cargo.toml @@ -12,10 +12,11 @@ description = "Universal Steam Deck Plugin Library front-end designed for WASM" crate-type = ["cdylib", "rlib"] [features] -default = [] +default = ["encrypt"] decky = ["usdpl-core/decky"] crankshaft = ["usdpl-core/crankshaft"] debug = ["console_error_panic_hook"] +encrypt = ["usdpl-core/encrypt", "obfstr", "hex"] [dependencies] wasm-bindgen = "0.2" @@ -44,7 +45,10 @@ web-sys = { version = "0.3", features = [ ]} js-sys = { version = "0.3" } -usdpl-core = { version = "0.5.0", path = "../usdpl-core" } +obfstr = { version = "0.3", optional = true } +hex = { version = "0.4", optional = true } + +usdpl-core = { version = "0.6.0", path = "../usdpl-core" } [dev-dependencies] wasm-bindgen-test = { version = "0.3.13" } diff --git a/usdpl-front/build.sh b/usdpl-front/build.sh index ba35fa9..a4d2eba 100755 --- a/usdpl-front/build.sh +++ b/usdpl-front/build.sh @@ -6,17 +6,17 @@ $0 [decky|crankshaft|]" exit 0 elif [ "$1" == "decky" ]; then echo "Building WASM module for decky framework" - wasm-pack build --target web --features decky + RUSTFLAGS="--cfg aes_compact" wasm-pack build --target web --features decky elif [ "$1" == "crankshaft" ]; then echo "WARNING: crankshaft support is unimplemented" - wasm-pack build --target web --features crankshaft + RUSTFLAGS="--cfg aes_compact" wasm-pack build --target web --features crankshaft else echo "Unsupported plugin framework \`$1\`" exit 1 fi else echo "WARNING: Building for any plugin framework, which may not work for every framework" - wasm-pack build --target web + RUSTFLAGS="--cfg aes_compact" wasm-pack build --target web fi python3 ./scripts/generate_embedded_wasm.py diff --git a/usdpl-front/src/connection.rs b/usdpl-front/src/connection.rs index 74e28f2..177b2be 100644 --- a/usdpl-front/src/connection.rs +++ b/usdpl-front/src/connection.rs @@ -13,18 +13,22 @@ use web_sys::{Request, RequestInit, RequestMode, Response}; use usdpl_core::serdes::{Dumpable, Loadable, Primitive}; use usdpl_core::socket; -pub async fn send_js(packet: socket::Packet, port: u16) -> Result, JsValue> { +const NONCE: [u8; socket::NONCE_SIZE]= [0u8; socket::NONCE_SIZE]; + +pub async fn send_js( + packet: socket::Packet, + port: u16, + #[cfg(feature = "encrypt")] + key: Vec, +) -> Result, JsValue> { let mut opts = RequestInit::new(); opts.method("POST"); opts.mode(RequestMode::Cors); let url = format!("http://{}:{}/usdpl/call", socket::HOST_STR, port); - let mut buffer = [0u8; socket::PACKET_BUFFER_SIZE]; - let len = packet - .dump_base64(&mut buffer) - .map_err(super::convert::str_to_js)?; - let string: String = String::from_utf8_lossy(&buffer[..len]).into(); + let (buffer, len) = dump_to_buffer(packet, #[cfg(feature = "encrypt")] key.as_slice())?; + let string: String = String::from_utf8_lossy(&buffer.as_slice()[..len]).into(); opts.body(Some(&string.into())); let request = Request::new_with_str_and_init(&url, &opts)?; @@ -39,6 +43,7 @@ pub async fn send_js(packet: socket::Packet, port: u16) -> Result let text = JsFuture::from(resp.text()?).await?; let string: JsString = text.dyn_into()?; + #[cfg(not(feature = "encrypt"))] match socket::Packet::load_base64(string.as_string().unwrap().as_bytes()) .map_err(super::convert::str_to_js)? .0 @@ -53,4 +58,40 @@ pub async fn send_js(packet: socket::Packet, port: u16) -> Result .into()) } } + + #[cfg(feature = "encrypt")] + match socket::Packet::load_encrypted(string.as_string().unwrap().as_bytes(), key.as_slice(), &NONCE) + .map_err(super::convert::str_to_js)? + .0 + { + socket::Packet::CallResponse(resp) => Ok(resp.response), + _ => { + //imports::console_warn(&format!("USDPL warning: Got non-call-response message from {}", resp.url())); + Err(format!( + "Expected call response message from {}, got something else", + resp.url() + ) + .into()) + } + } +} + +#[cfg(feature = "encrypt")] +fn dump_to_buffer(packet: socket::Packet, key: &[u8]) -> Result<(Vec, usize), JsValue> { + let mut buffer = Vec::with_capacity(socket::PACKET_BUFFER_SIZE); + buffer.extend_from_slice(&[0u8; socket::PACKET_BUFFER_SIZE]); + let len = packet + .dump_encrypted(&mut buffer, key, &NONCE) + .map_err(super::convert::str_to_js)?; + Ok((buffer, len)) +} + +#[cfg(not(feature = "encrypt"))] +fn dump_to_buffer(packet: socket::Packet) -> Result<(Vec, usize), JsValue> { + let mut buffer = Vec::with_capacity(socket::PACKET_BUFFER_SIZE); + buffer.extend_from_slice(&[0u8; socket::PACKET_BUFFER_SIZE]); + let len = packet + .dump_base64(buffer.as_mut_slice()) + .map_err(super::convert::str_to_js)?; + Ok((buffer, len)) } diff --git a/usdpl-front/src/lib.rs b/usdpl-front/src/lib.rs index a91f018..2b79b7e 100644 --- a/usdpl-front/src/lib.rs +++ b/usdpl-front/src/lib.rs @@ -16,19 +16,30 @@ use usdpl_core::{socket::Packet, RemoteCall}; //const REMOTE_CALL_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); //const REMOTE_PORT: std::sync::atomic::AtomicU16 = std::sync::atomic::AtomicU16::new(31337); -static mut CTX: UsdplContext = UsdplContext { port: 31337, id: 1 }; +static mut CTX: UsdplContext = UsdplContext { port: 31337, id: 1, key: Vec::new() }; + +#[cfg(feature = "encrypt")] +fn encryption_key() -> Vec { + hex::decode(obfstr::obfstr!(env!("USDPL_ENCRYPTION_KEY"))).unwrap() +} //#[wasm_bindgen] #[derive(Debug)] struct UsdplContext { port: u16, id: u64, + #[cfg(feature = "encrypt")] + key: Vec, } fn get_port() -> u16 { unsafe { CTX.port } } +fn get_key() -> Vec { + unsafe { CTX.key.clone() } +} + fn increment_id() -> u64 { let current_id = unsafe { CTX.id }; unsafe { @@ -49,7 +60,12 @@ pub fn init_usdpl(port: u16) { console_error_panic_hook::set_once(); //REMOTE_PORT.store(port, std::sync::atomic::Ordering::SeqCst); unsafe { - CTX = UsdplContext { port: port, id: 1 }; + CTX = UsdplContext { + port: port, + id: 1, + #[cfg(feature = "encrypt")] + key: encryption_key(), + }; } } @@ -84,6 +100,8 @@ pub async fn call_backend(name: String, parameters: Vec) -> JsValue { parameters: params, }), port, + #[cfg(feature = "encrypt")] + get_key() ) .await; let results = match results {