diff --git a/src/mc_types.rs b/src/mc_types.rs index 8d66da4..adc1091 100644 --- a/src/mc_types.rs +++ b/src/mc_types.rs @@ -1,22 +1,17 @@ // Yeahbut December 2023 -use std::error::Error; -use std::fmt; +mod error; +mod protocol; + +use std::error::Error; -use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf}; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; use serde::{Serialize, Deserialize}; use async_trait::async_trait; -use rsa::{RsaPrivateKey, RsaPublicKey}; -use rsa::pkcs8::{EncodePublicKey, DecodePublicKey}; -use rand::Rng; -use crypto::digest::Digest; -use sha1::Sha1; -use num_bigint::BigInt; -use crate::login; -use crate::encrypt::{self, McCipher}; -use crate::play::Play; +use crate::mc_types::protocol::ProtocolWrite; + +pub use crate::mc_types::error::PacketError; +pub use crate::mc_types::protocol::{ProtocolRead, ProtocolConnection}; pub type Result = std::result::Result>; @@ -26,352 +21,11 @@ pub const VERSION_PROTOCOL: i32 = 767; const SEGMENT_BITS: u8 = 0x7F; const CONTINUE_BIT: u8 = 0x80; -#[derive(Debug)] -pub enum PacketError { - ValueTooLarge, - RanOutOfBytes, - InvalidPacketId(i32), - InvalidUUIDString, - EncryptionError, -} - -impl fmt::Display for PacketError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - PacketError::ValueTooLarge => - write!(f, "VarInt value is too large"), - PacketError::RanOutOfBytes => - write!(f, "Ran out of bytes while reading VarInt"), - PacketError::InvalidPacketId(packet_id) => - write!(f, "Invalid packet id: {}", packet_id), - PacketError::InvalidUUIDString => - write!(f, "Invalid UUID format"), - PacketError::EncryptionError => - write!(f, "Encryption Error"), - } - } -} - -impl Error for PacketError {} - #[derive(Serialize, Deserialize)] pub struct Chat { pub text: String, } -#[async_trait] -pub trait ProtocolRead { - async fn read_data(&mut self) -> Result>; -} - -#[async_trait] -pub trait ProtocolWrite { - async fn write_data(&mut self, data: &mut Vec) -> Result<()>; -} - -pub struct ProtocolConnection<'a> { - pub stream_read: &'a mut OwnedReadHalf, - pub stream_write: &'a mut OwnedWriteHalf, - rsa_private_key: Option, - rsa_public_key: Option, - aes_cipher: Option, - verify_token: Option<[u8; 16]>, - server_id: String -} - -impl<'a> ProtocolConnection<'a> { - pub fn new( - stream_read: &'a mut OwnedReadHalf, - stream_write: &'a mut OwnedWriteHalf, - ) -> Self { - ProtocolConnection { - stream_read, - stream_write, - rsa_private_key: None, - rsa_public_key: None, - aes_cipher: None, - verify_token: None, - server_id: "".to_string(), - } - } - - pub fn create_encryption_request( - &mut self, - private_key: RsaPrivateKey, - ) -> Result { - match self.rsa_private_key { - Some(_) => {}, - None => { - let public_key = RsaPublicKey::from(&private_key); - let mut rng = rand::thread_rng(); - self.rsa_private_key = Some(private_key); - self.rsa_public_key = Some(public_key); - self.verify_token = Some(rng.gen()); - } - }; - match &self.rsa_public_key { - Some (key) => { - match &self.verify_token { - Some (token) => - Ok(login::clientbound::EncryptionRequest { - server_id: self.server_id.clone(), - public_key: key - .to_public_key_der()? - .as_ref() - .to_vec(), - verify_token: token[0..16].to_vec(), - }), - None => Err(Box::new(PacketError::EncryptionError)) - } - }, - None => Err(Box::new(PacketError::EncryptionError)) - } - } - - pub fn handle_encryption_request( - &mut self, - request: login::clientbound::EncryptionRequest, - ) -> Result { - self.server_id = request.server_id; - self.rsa_public_key = Some( - RsaPublicKey::from_public_key_der(&request.public_key)?); - self.aes_cipher = Some(McCipher::create()); - match &self.aes_cipher { - Some(aes_cipher) => { - match &self.rsa_public_key { - Some(public_key) => { - Ok(login::serverbound::EncryptionResponse { - shared_secret: aes_cipher - .get_encrypted_key(public_key)?, - verify_token: encrypt::encrypt_rsa( - public_key, - request.verify_token[0..16] - .try_into() - .unwrap(), - )?, - }) - }, - None => Err(Box::new(PacketError::EncryptionError)) - } - }, - None => Err(Box::new(PacketError::EncryptionError)) - } - } - - pub fn handle_encryption_response( - &mut self, - response: login::serverbound::EncryptionResponse, - ) -> Result<()> { - match &self.verify_token { - Some (token) => { - match &self.rsa_private_key { - Some (private_key) => { - if &encrypt::decrypt_rsa( - &private_key, - response.verify_token.as_slice() - )? == token { - self.aes_cipher = - Some(McCipher::create_with_encrypted_key( - private_key, - response.shared_secret.as_slice(), - )?); - Ok(()) - } else { - Err(Box::new(PacketError::EncryptionError)) - } - } - None => Err(Box::new(PacketError::EncryptionError)) - } - } - None => Err(Box::new(PacketError::EncryptionError)) - } - } - - pub async fn forward_play( - &mut self, - other: &mut ProtocolConnection<'_>, - ) -> Result<()> { - loop { - let packet = Play::read(self).await?; - match packet { - Play::PlayPacket(packet) => packet.write(other).await?, - }; - } - } - - pub fn split_conn( - &mut self - ) -> Result<(WriteHaftProtocolConnection, ReadHaftProtocolConnection)> { - Ok((WriteHaftProtocolConnection { - stream_write: &mut self.stream_write, - aes_cipher: self.aes_cipher.clone(), - }, - ReadHaftProtocolConnection { - stream_read: &mut self.stream_read, - aes_cipher: self.aes_cipher.clone(), - })) - } - - pub async fn server_id_hash(&self) -> Result { - let hash_data = match &self.aes_cipher { - Some(aes_cipher) => match &self.rsa_public_key { - Some(key) => [ - self.server_id.as_bytes(), - &aes_cipher.key, - key.to_public_key_der()?.as_ref(), - ].concat(), - None => return Err(Box::new(PacketError::EncryptionError)) - }, - None => return Err(Box::new(PacketError::EncryptionError)) - }; - let hash = BigInt::from_signed_bytes_be( - &Sha1::digest(hash_data)).to_str_radix(16); - Ok(hash) - } -} - -unsafe impl<'a> Send for ProtocolConnection<'a> {} - -#[async_trait] -impl<'a> ProtocolRead for ProtocolConnection<'a> { - async fn read_data(&mut self) -> Result> { - match &mut self.aes_cipher { - Some(aes_cipher) => { - let length = read_var_int_stream_encrypted( - self.stream_read, aes_cipher).await? as usize; - - let mut buffer: Vec = vec![0; length]; - self.stream_read.read_exact(&mut buffer).await?; - Ok(aes_cipher.decrypt_aes(buffer)) - }, - None => { - let length = read_var_int_stream( - self.stream_read).await? as usize; - - let mut buffer: Vec = vec![0; length]; - self.stream_read.read_exact(&mut buffer).await?; - - Ok(buffer) - } - } - } -} - -#[async_trait] -impl<'a> ProtocolWrite for ProtocolConnection<'a> { - async fn write_data(&mut self, data: &mut Vec) -> Result<()> { - let mut out_data = convert_var_int(data.len() as i32); - out_data.append(data); - match &mut self.aes_cipher { - Some(aes_cipher) => { - self.stream_write.write_all( - &aes_cipher.encrypt_aes(out_data)).await?; - - Ok(()) - }, - None => { - self.stream_write.write_all(&out_data).await?; - - Ok(()) - } - } - } -} - -pub struct WriteHaftProtocolConnection<'a> { - pub stream_write: &'a mut OwnedWriteHalf, - aes_cipher: Option, -} - -impl<'a> WriteHaftProtocolConnection<'a> { - pub fn new( - stream_write: &'a mut OwnedWriteHalf, - ) -> Self { - WriteHaftProtocolConnection { - stream_write, - aes_cipher: None, - } - } -} - -unsafe impl<'a> Send for WriteHaftProtocolConnection<'a> {} - -#[async_trait] -impl<'a> ProtocolWrite for WriteHaftProtocolConnection<'a> { - async fn write_data(&mut self, data: &mut Vec) -> Result<()> { - let mut out_data = convert_var_int(data.len() as i32); - out_data.append(data); - match &mut self.aes_cipher { - Some(aes_cipher) => { - self.stream_write.write_all( - &aes_cipher.encrypt_aes(out_data)).await?; - - Ok(()) - }, - None => { - self.stream_write.write_all(&out_data).await?; - - Ok(()) - } - } - } -} - -pub struct ReadHaftProtocolConnection<'a> { - pub stream_read: &'a mut OwnedReadHalf, - aes_cipher: Option, -} - -impl<'a> ReadHaftProtocolConnection<'a> { - pub fn new( - stream_read: &'a mut OwnedReadHalf, - ) -> Self { - ReadHaftProtocolConnection { - stream_read, - aes_cipher: None, - } - } - - pub async fn forward_play( - &mut self, - other: &mut T, - ) -> Result<()> { - loop { - let packet = Play::read(self).await?; - match packet { - Play::PlayPacket(packet) => packet.write(other).await?, - }; - } - } -} - -unsafe impl<'a> Send for ReadHaftProtocolConnection<'a> {} - -#[async_trait] -impl<'a> ProtocolRead for ReadHaftProtocolConnection<'a> { - async fn read_data(&mut self) -> Result> { - match &mut self.aes_cipher { - Some(aes_cipher) => { - let length = read_var_int_stream_encrypted( - self.stream_read, aes_cipher).await? as usize; - - let mut buffer: Vec = vec![0; length]; - self.stream_read.read_exact(&mut buffer).await?; - Ok(aes_cipher.decrypt_aes(buffer)) - }, - None => { - let length = read_var_int_stream( - self.stream_read).await? as usize; - - let mut buffer: Vec = vec![0; length]; - self.stream_read.read_exact(&mut buffer).await?; - - Ok(buffer) - } - } - } -} - #[async_trait] pub trait Packet: Sized { fn packet_id() -> i32; @@ -393,45 +47,6 @@ pub trait Packet: Sized { } } -async fn read_var_int_stream(stream: &mut OwnedReadHalf) -> Result { - let mut data: Vec = vec![]; - - loop { - let current_byte = stream.read_u8().await?; - - data.append(&mut vec![current_byte]); - - if (current_byte & CONTINUE_BIT) == 0 { - break; - } - } - - let varint = get_var_int(&mut data)?; - - Ok(varint) -} -async fn read_var_int_stream_encrypted( - stream: &mut OwnedReadHalf, - cipher: &mut McCipher, -) -> Result { - let mut data: Vec = vec![]; - - loop { - let encrypted_byte = stream.read_u8().await?; - let current_byte = cipher.decrypt_aes(vec![encrypted_byte])[0]; - - data.append(&mut vec![current_byte]); - - if (current_byte & CONTINUE_BIT) == 0 { - break; - } - } - - let varint = get_var_int(&mut data)?; - - Ok(varint) -} - pub trait PacketArray: Sized { fn get(data: &mut Vec) -> Result; fn convert(&self) -> Vec; diff --git a/src/mc_types/error.rs b/src/mc_types/error.rs new file mode 100644 index 0000000..c0dacad --- /dev/null +++ b/src/mc_types/error.rs @@ -0,0 +1,32 @@ +// Yeahbut September 2025 + +use std::fmt; +use std::error::Error; + +#[derive(Debug)] +pub enum PacketError { + ValueTooLarge, + RanOutOfBytes, + InvalidPacketId(i32), + InvalidUUIDString, + EncryptionError, +} + +impl fmt::Display for PacketError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + PacketError::ValueTooLarge => + write!(f, "VarInt value is too large"), + PacketError::RanOutOfBytes => + write!(f, "Ran out of bytes while reading VarInt"), + PacketError::InvalidPacketId(packet_id) => + write!(f, "Invalid packet id: {}", packet_id), + PacketError::InvalidUUIDString => + write!(f, "Invalid UUID format"), + PacketError::EncryptionError => + write!(f, "Encryption Error"), + } + } +} + +impl Error for PacketError {} diff --git a/src/mc_types/protocol.rs b/src/mc_types/protocol.rs new file mode 100644 index 0000000..d59b957 --- /dev/null +++ b/src/mc_types/protocol.rs @@ -0,0 +1,369 @@ +// Yeahbut September 2025 + +use async_trait::async_trait; +use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use rsa::{RsaPrivateKey, RsaPublicKey}; +use rsa::pkcs8::{EncodePublicKey, DecodePublicKey}; +use num_bigint::BigInt; +use sha1::Sha1; +use rand::Rng; +use crypto::digest::Digest; + +use crate::encrypt::{self, McCipher}; +use crate::login; +use crate::play::Play; + +use crate::mc_types::*; + +#[async_trait] +pub trait ProtocolRead { + async fn read_data(&mut self) -> Result>; +} + +#[async_trait] +pub trait ProtocolWrite { + async fn write_data(&mut self, data: &mut Vec) -> Result<()>; +} + +pub struct ProtocolConnection<'a> { + pub stream_read: &'a mut OwnedReadHalf, + pub stream_write: &'a mut OwnedWriteHalf, + rsa_private_key: Option, + rsa_public_key: Option, + aes_cipher: Option, + verify_token: Option<[u8; 16]>, + server_id: String +} + +impl<'a> ProtocolConnection<'a> { + pub fn new( + stream_read: &'a mut OwnedReadHalf, + stream_write: &'a mut OwnedWriteHalf, + ) -> Self { + ProtocolConnection { + stream_read, + stream_write, + rsa_private_key: None, + rsa_public_key: None, + aes_cipher: None, + verify_token: None, + server_id: "".to_string(), + } + } + + pub fn create_encryption_request( + &mut self, + private_key: RsaPrivateKey, + ) -> Result { + match self.rsa_private_key { + Some(_) => {}, + None => { + let public_key = RsaPublicKey::from(&private_key); + let mut rng = rand::thread_rng(); + self.rsa_private_key = Some(private_key); + self.rsa_public_key = Some(public_key); + self.verify_token = Some(rng.gen()); + } + }; + match &self.rsa_public_key { + Some (key) => { + match &self.verify_token { + Some (token) => + Ok(login::clientbound::EncryptionRequest { + server_id: self.server_id.clone(), + public_key: key + .to_public_key_der()? + .as_ref() + .to_vec(), + verify_token: token[0..16].to_vec(), + }), + None => Err(Box::new(PacketError::EncryptionError)) + } + }, + None => Err(Box::new(PacketError::EncryptionError)) + } + } + + pub fn handle_encryption_request( + &mut self, + request: login::clientbound::EncryptionRequest, + ) -> Result { + self.server_id = request.server_id; + self.rsa_public_key = Some( + RsaPublicKey::from_public_key_der(&request.public_key)?); + self.aes_cipher = Some(McCipher::create()); + match &self.aes_cipher { + Some(aes_cipher) => { + match &self.rsa_public_key { + Some(public_key) => { + Ok(login::serverbound::EncryptionResponse { + shared_secret: aes_cipher + .get_encrypted_key(public_key)?, + verify_token: encrypt::encrypt_rsa( + public_key, + request.verify_token[0..16] + .try_into() + .unwrap(), + )?, + }) + }, + None => Err(Box::new(PacketError::EncryptionError)) + } + }, + None => Err(Box::new(PacketError::EncryptionError)) + } + } + + pub fn handle_encryption_response( + &mut self, + response: login::serverbound::EncryptionResponse, + ) -> Result<()> { + match &self.verify_token { + Some (token) => { + match &self.rsa_private_key { + Some (private_key) => { + if &encrypt::decrypt_rsa( + &private_key, + response.verify_token.as_slice() + )? == token { + self.aes_cipher = + Some(McCipher::create_with_encrypted_key( + private_key, + response.shared_secret.as_slice(), + )?); + Ok(()) + } else { + Err(Box::new(PacketError::EncryptionError)) + } + } + None => Err(Box::new(PacketError::EncryptionError)) + } + } + None => Err(Box::new(PacketError::EncryptionError)) + } + } + + pub async fn forward_play( + &mut self, + other: &mut ProtocolConnection<'_>, + ) -> Result<()> { + loop { + let packet = Play::read(self).await?; + match packet { + Play::PlayPacket(packet) => packet.write(other).await?, + }; + } + } + + pub fn split_conn( + &mut self + ) -> Result<(WriteHaftProtocolConnection, ReadHaftProtocolConnection)> { + Ok((WriteHaftProtocolConnection { + stream_write: &mut self.stream_write, + aes_cipher: self.aes_cipher.clone(), + }, + ReadHaftProtocolConnection { + stream_read: &mut self.stream_read, + aes_cipher: self.aes_cipher.clone(), + })) + } + + pub async fn server_id_hash(&self) -> Result { + let hash_data = match &self.aes_cipher { + Some(aes_cipher) => match &self.rsa_public_key { + Some(key) => [ + self.server_id.as_bytes(), + &aes_cipher.key, + key.to_public_key_der()?.as_ref(), + ].concat(), + None => return Err(Box::new(PacketError::EncryptionError)) + }, + None => return Err(Box::new(PacketError::EncryptionError)) + }; + let hash = BigInt::from_signed_bytes_be( + &Sha1::digest(hash_data)).to_str_radix(16); + Ok(hash) + } +} + +unsafe impl<'a> Send for ProtocolConnection<'a> {} + +#[async_trait] +impl<'a> ProtocolRead for ProtocolConnection<'a> { + async fn read_data(&mut self) -> Result> { + match &mut self.aes_cipher { + Some(aes_cipher) => { + let length = read_var_int_stream_encrypted( + self.stream_read, aes_cipher).await? as usize; + + let mut buffer: Vec = vec![0; length]; + self.stream_read.read_exact(&mut buffer).await?; + Ok(aes_cipher.decrypt_aes(buffer)) + }, + None => { + let length = read_var_int_stream( + self.stream_read).await? as usize; + + let mut buffer: Vec = vec![0; length]; + self.stream_read.read_exact(&mut buffer).await?; + + Ok(buffer) + } + } + } +} + +#[async_trait] +impl<'a> ProtocolWrite for ProtocolConnection<'a> { + async fn write_data(&mut self, data: &mut Vec) -> Result<()> { + let mut out_data = convert_var_int(data.len() as i32); + out_data.append(data); + match &mut self.aes_cipher { + Some(aes_cipher) => { + self.stream_write.write_all( + &aes_cipher.encrypt_aes(out_data)).await?; + + Ok(()) + }, + None => { + self.stream_write.write_all(&out_data).await?; + + Ok(()) + } + } + } +} + +pub struct WriteHaftProtocolConnection<'a> { + pub stream_write: &'a mut OwnedWriteHalf, + aes_cipher: Option, +} + +impl<'a> WriteHaftProtocolConnection<'a> { + pub fn new( + stream_write: &'a mut OwnedWriteHalf, + ) -> Self { + WriteHaftProtocolConnection { + stream_write, + aes_cipher: None, + } + } +} + +unsafe impl<'a> Send for WriteHaftProtocolConnection<'a> {} + +#[async_trait] +impl<'a> ProtocolWrite for WriteHaftProtocolConnection<'a> { + async fn write_data(&mut self, data: &mut Vec) -> Result<()> { + let mut out_data = convert_var_int(data.len() as i32); + out_data.append(data); + match &mut self.aes_cipher { + Some(aes_cipher) => { + self.stream_write.write_all( + &aes_cipher.encrypt_aes(out_data)).await?; + + Ok(()) + }, + None => { + self.stream_write.write_all(&out_data).await?; + + Ok(()) + } + } + } +} + +pub struct ReadHaftProtocolConnection<'a> { + pub stream_read: &'a mut OwnedReadHalf, + aes_cipher: Option, +} + +impl<'a> ReadHaftProtocolConnection<'a> { + pub fn new( + stream_read: &'a mut OwnedReadHalf, + ) -> Self { + ReadHaftProtocolConnection { + stream_read, + aes_cipher: None, + } + } + + pub async fn forward_play( + &mut self, + other: &mut T, + ) -> Result<()> { + loop { + let packet = Play::read(self).await?; + match packet { + Play::PlayPacket(packet) => packet.write(other).await?, + }; + } + } +} + +unsafe impl<'a> Send for ReadHaftProtocolConnection<'a> {} + +#[async_trait] +impl<'a> ProtocolRead for ReadHaftProtocolConnection<'a> { + async fn read_data(&mut self) -> Result> { + match &mut self.aes_cipher { + Some(aes_cipher) => { + let length = read_var_int_stream_encrypted( + self.stream_read, aes_cipher).await? as usize; + + let mut buffer: Vec = vec![0; length]; + self.stream_read.read_exact(&mut buffer).await?; + Ok(aes_cipher.decrypt_aes(buffer)) + }, + None => { + let length = read_var_int_stream( + self.stream_read).await? as usize; + + let mut buffer: Vec = vec![0; length]; + self.stream_read.read_exact(&mut buffer).await?; + + Ok(buffer) + } + } + } +} + +async fn read_var_int_stream(stream: &mut OwnedReadHalf) -> Result { + let mut data: Vec = vec![]; + + loop { + let current_byte = stream.read_u8().await?; + + data.append(&mut vec![current_byte]); + + if (current_byte & CONTINUE_BIT) == 0 { + break; + } + } + + let varint = get_var_int(&mut data)?; + + Ok(varint) +} +async fn read_var_int_stream_encrypted( + stream: &mut OwnedReadHalf, + cipher: &mut McCipher, +) -> Result { + let mut data: Vec = vec![]; + + loop { + let encrypted_byte = stream.read_u8().await?; + let current_byte = cipher.decrypt_aes(vec![encrypted_byte])[0]; + + data.append(&mut vec![current_byte]); + + if (current_byte & CONTINUE_BIT) == 0 { + break; + } + } + + let varint = get_var_int(&mut data)?; + + Ok(varint) +}