diff --git a/src/encryption.rs b/src/encryption.rs new file mode 100644 index 0000000..9662529 --- /dev/null +++ b/src/encryption.rs @@ -0,0 +1,117 @@ +use std::{ + fmt::Display, + io::{BufRead, BufReader, Write}, + net::TcpStream, +}; + +use openssl::{ + pkey::Private, + rsa::Rsa, + symm::{decrypt, encrypt, Cipher}, +}; + +fn aes_encrypt( + key: &[u8], + // iv: &[u8], + plaintext: &[u8], +) -> Result, Box> { + let cipher = Cipher::aes_256_ecb(); + let ciphertext = encrypt(cipher, key, None, plaintext)?; + Ok(ciphertext) +} + +fn aes_decrypt( + key: &[u8], + // iv: &[u8], + ciphertext: &[u8], +) -> Result, Box> { + let cipher = Cipher::aes_256_ecb(); + let plaintext = decrypt(cipher, key, None, ciphertext)?; + Ok(plaintext) +} + +#[allow(deprecated)] +pub fn handshake(mut stream: TcpStream, rsa: Rsa) -> ETcp { + let mut reader = BufReader::new(stream.try_clone().unwrap()); + + stream.write_all(&rsa.public_key_to_pem().unwrap()).unwrap(); + + stream.flush().unwrap(); + + let mut aes_encoded = String::new(); + + reader.read_line(&mut aes_encoded).unwrap(); + + let encrypted_data = base64::decode(aes_encoded.trim()).expect("Failed to decode base64"); + + let mut aes_decrypted = vec![0; 256]; + + let aes_len = rsa + .private_decrypt( + &encrypted_data, + &mut aes_decrypted, + openssl::rsa::Padding::PKCS1, + ) + .expect("Decryption failed"); + + println!("len: {}", aes_len); + + aes_decrypted.truncate(aes_len); + + println!( + "Decrypted AES key ({} bytes): {:?}", + aes_decrypted.len(), + aes_decrypted + ); + + ETcp { + stream, + aes: aes_decrypted, + reader, + } +} + +pub struct ETcp { + stream: TcpStream, + reader: BufReader, + aes: Vec, +} + +impl ETcp { + #[allow(deprecated)] + pub fn send(&mut self, d: T) { + let a = aes_encrypt(&self.aes, d.to_string().as_bytes()).unwrap(); + + self.stream + .write_all((base64::encode(a) + "\n").as_bytes()) + .unwrap(); + + self.stream.flush().unwrap(); + } + + #[allow(deprecated)] + pub fn read(&mut self) -> Option { + let mut v_encoded = String::new(); + + self.reader.read_line(&mut v_encoded).unwrap(); + + let encrypted_data = base64::decode(v_encoded.trim()).expect("Failed to decode base64"); + + Some(String::from_utf8(aes_decrypt(&self.aes, &encrypted_data).unwrap()).unwrap()) + } + + pub fn close(&self) { + self.stream + .shutdown(std::net::Shutdown::Both) + .expect("shutdown call failed"); + } + + pub fn clone(&mut self) -> Self { + let stream = self.stream.try_clone().unwrap(); + ETcp { + reader: BufReader::new(stream.try_clone().unwrap()), + stream, + aes: self.aes.clone(), + } + } +} diff --git a/src/main.rs b/src/main.rs index dd6ba85..03ed25f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ use std::{ - io::{BufRead, BufReader, Write}, net::TcpListener, sync::Arc, time::{Duration, Instant}, @@ -36,6 +35,17 @@ fn main() -> std::io::Result<()> { stream.send(res); loop { + // Check for inactivity + if last_activity.elapsed() > Duration::from_secs(60) { + println!( + "[MOJANG] {} inactive for too long", + session.local_player.name + ); + methods::player::logout(&session).unwrap(); + println!("[MOJANG] {} went offline", session.local_player.name); + break; + } + match stream.read() { None => { // Client disconnected @@ -54,29 +64,12 @@ fn main() -> std::io::Result<()> { Err(e) => format!("!{e}"), }); } - // Err(e) => { - // println!( - // "[ERROR] Read error for {}: {}", - // session.local_player.name, e - // ); - // break; - // } }; - - // Check for inactivity - if last_activity.elapsed() > Duration::from_secs(60) { - println!( - "[MOJANG] {} inactive for too long", - session.local_player.name - ); - methods::player::logout(&session).unwrap(); - println!("[MOJANG] {} went offline", session.local_player.name); - break; - } } } Err(e) => { - // stream.write_all(format!("!{e}").as_bytes()).unwrap(); + stream.send(format!("!{e}")); + println!("Disconnected"); stream.close(); } }