mc_types::error and mc_types::protocol created

This commit is contained in:
Kyler Olsen 2025-09-13 00:08:05 -06:00
parent 50c6b27ec8
commit 5f715d7688
3 changed files with 409 additions and 393 deletions

View File

@ -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<T> = std::result::Result<T, Box<dyn Error>>;
@ -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<Vec<u8>>;
}
#[async_trait]
pub trait ProtocolWrite {
async fn write_data(&mut self, data: &mut Vec<u8>) -> Result<()>;
}
pub struct ProtocolConnection<'a> {
pub stream_read: &'a mut OwnedReadHalf,
pub stream_write: &'a mut OwnedWriteHalf,
rsa_private_key: Option<RsaPrivateKey>,
rsa_public_key: Option<RsaPublicKey>,
aes_cipher: Option<McCipher>,
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<login::clientbound::EncryptionRequest> {
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<login::serverbound::EncryptionResponse> {
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<String> {
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<Vec<u8>> {
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<u8> = 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<u8> = 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<u8>) -> 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<McCipher>,
}
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<u8>) -> 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<McCipher>,
}
impl<'a> ReadHaftProtocolConnection<'a> {
pub fn new(
stream_read: &'a mut OwnedReadHalf,
) -> Self {
ReadHaftProtocolConnection {
stream_read,
aes_cipher: None,
}
}
pub async fn forward_play<T: ProtocolWrite + Send>(
&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<Vec<u8>> {
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<u8> = 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<u8> = 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<i32> {
let mut data: Vec<u8> = 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<i32> {
let mut data: Vec<u8> = 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<u8>) -> Result<Self>;
fn convert(&self) -> Vec<u8>;

32
src/mc_types/error.rs Normal file
View File

@ -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 {}

369
src/mc_types/protocol.rs Normal file
View File

@ -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<Vec<u8>>;
}
#[async_trait]
pub trait ProtocolWrite {
async fn write_data(&mut self, data: &mut Vec<u8>) -> Result<()>;
}
pub struct ProtocolConnection<'a> {
pub stream_read: &'a mut OwnedReadHalf,
pub stream_write: &'a mut OwnedWriteHalf,
rsa_private_key: Option<RsaPrivateKey>,
rsa_public_key: Option<RsaPublicKey>,
aes_cipher: Option<McCipher>,
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<login::clientbound::EncryptionRequest> {
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<login::serverbound::EncryptionResponse> {
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<String> {
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<Vec<u8>> {
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<u8> = 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<u8> = 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<u8>) -> 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<McCipher>,
}
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<u8>) -> 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<McCipher>,
}
impl<'a> ReadHaftProtocolConnection<'a> {
pub fn new(
stream_read: &'a mut OwnedReadHalf,
) -> Self {
ReadHaftProtocolConnection {
stream_read,
aes_cipher: None,
}
}
pub async fn forward_play<T: ProtocolWrite + Send>(
&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<Vec<u8>> {
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<u8> = 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<u8> = vec![0; length];
self.stream_read.read_exact(&mut buffer).await?;
Ok(buffer)
}
}
}
}
async fn read_var_int_stream(stream: &mut OwnedReadHalf) -> Result<i32> {
let mut data: Vec<u8> = 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<i32> {
let mut data: Vec<u8> = 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)
}