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
|
// Yeahbut December 2023
|
||||||
|
|
||||||
use std::error::Error;
|
mod error;
|
||||||
use std::fmt;
|
mod protocol;
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use async_trait::async_trait;
|
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::mc_types::protocol::ProtocolWrite;
|
||||||
use crate::encrypt::{self, McCipher};
|
|
||||||
use crate::play::Play;
|
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>>;
|
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 SEGMENT_BITS: u8 = 0x7F;
|
||||||
const CONTINUE_BIT: u8 = 0x80;
|
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)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Chat {
|
pub struct Chat {
|
||||||
pub text: String,
|
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]
|
#[async_trait]
|
||||||
pub trait Packet: Sized {
|
pub trait Packet: Sized {
|
||||||
fn packet_id() -> i32;
|
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 {
|
pub trait PacketArray: Sized {
|
||||||
fn get(data: &mut Vec<u8>) -> Result<Self>;
|
fn get(data: &mut Vec<u8>) -> Result<Self>;
|
||||||
fn convert(&self) -> Vec<u8>;
|
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