mc_types::error and mc_types::protocol created
This commit is contained in:
parent
50c6b27ec8
commit
5f715d7688
401
src/mc_types.rs
401
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<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>;
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
|
@ -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)
|
||||
}
|
||||
Loading…
Reference in New Issue